mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Add fx to ErrorType
This commit is contained in:
parent
8a65617704
commit
6533e9084d
6 changed files with 66 additions and 30 deletions
|
@ -5419,9 +5419,9 @@ mod test_reporting {
|
||||||
6│ 2 -> 2
|
6│ 2 -> 2
|
||||||
^^
|
^^
|
||||||
|
|
||||||
Looks like you are trying to define a function.
|
Looks like you are trying to define a function.
|
||||||
|
|
||||||
In Roc, functions are always written as a lambda, like
|
In Roc, functions are always written as a lambda, like
|
||||||
|
|
||||||
increment = \n -> n + 1
|
increment = \n -> n + 1
|
||||||
"#
|
"#
|
||||||
|
|
|
@ -57,8 +57,8 @@ pub fn remove_module_param_arguments(
|
||||||
drop_last_argument(expected);
|
drop_last_argument(expected);
|
||||||
|
|
||||||
if let (
|
if let (
|
||||||
ErrorType::Function(found_args, _, _),
|
ErrorType::Function(found_args, _, _, _),
|
||||||
ErrorType::Function(expected_args, _, _),
|
ErrorType::Function(expected_args, _, _, _),
|
||||||
) = (found, expected)
|
) = (found, expected)
|
||||||
{
|
{
|
||||||
if found_args.len() > expected_args.len() {
|
if found_args.len() > expected_args.len() {
|
||||||
|
@ -194,7 +194,7 @@ fn remove_for_reason(
|
||||||
|
|
||||||
fn drop_last_argument(err_type: &mut ErrorType) {
|
fn drop_last_argument(err_type: &mut ErrorType) {
|
||||||
match err_type {
|
match err_type {
|
||||||
ErrorType::Function(arguments, _, _) => {
|
ErrorType::Function(arguments, _, _, _) => {
|
||||||
arguments.pop();
|
arguments.pop();
|
||||||
}
|
}
|
||||||
// Irrelevant
|
// Irrelevant
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
name_type_var, AbilitySet, AliasKind, ErrorType, ExtImplicitOpenness, Polarity, RecordField,
|
name_type_var, AbilitySet, AliasKind, ErrorFunctionFx, ErrorType, ExtImplicitOpenness,
|
||||||
RecordFieldsError, TupleElemsError, TypeExt, Uls,
|
Polarity, RecordField, RecordFieldsError, TupleElemsError, TypeExt, Uls,
|
||||||
};
|
};
|
||||||
use crate::unification_table::{self, UnificationTable};
|
use crate::unification_table::{self, UnificationTable};
|
||||||
use roc_collections::all::{FnvMap, ImMap, ImSet, MutSet, SendMap};
|
use roc_collections::all::{FnvMap, ImMap, ImSet, MutSet, SendMap};
|
||||||
|
@ -4206,7 +4206,7 @@ fn flat_type_to_err_type(
|
||||||
ErrorType::Type(symbol, arg_types)
|
ErrorType::Type(symbol, arg_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
Func(arg_vars, closure_var, ret_var, _fx_var) => {
|
Func(arg_vars, closure_var, ret_var, fx_var) => {
|
||||||
let args = arg_vars
|
let args = arg_vars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|index| {
|
.map(|index| {
|
||||||
|
@ -4217,9 +4217,23 @@ fn flat_type_to_err_type(
|
||||||
|
|
||||||
let ret = var_to_err_type(subs, state, ret_var, Polarity::Pos);
|
let ret = var_to_err_type(subs, state, ret_var, Polarity::Pos);
|
||||||
let closure = var_to_err_type(subs, state, closure_var, pol);
|
let closure = var_to_err_type(subs, state, closure_var, pol);
|
||||||
|
let fx = match subs.get_content_without_compacting(fx_var) {
|
||||||
|
Content::Pure | Content::FlexVar(_) | Content::Error => ErrorFunctionFx::Pure,
|
||||||
|
Content::Effectful => ErrorFunctionFx::Effectful,
|
||||||
|
Content::RigidVar(_)
|
||||||
|
| Content::FlexAbleVar(_, _)
|
||||||
|
| Content::RigidAbleVar(_, _)
|
||||||
|
| Content::RecursionVar { .. }
|
||||||
|
| Content::LambdaSet(_)
|
||||||
|
| Content::ErasedLambda
|
||||||
|
| Content::Structure(_)
|
||||||
|
| Content::Alias(_, _, _, _)
|
||||||
|
| Content::RangedNumber(_) => {
|
||||||
|
internal_error!("Unexpected content in fx var")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// [purity-inference] TODO: add fx var to the error type
|
ErrorType::Function(args, Box::new(closure), fx, Box::new(ret))
|
||||||
ErrorType::Function(args, Box::new(closure), Box::new(ret))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmptyRecord => ErrorType::Record(SendMap::default(), TypeExt::Closed),
|
EmptyRecord => ErrorType::Record(SendMap::default(), TypeExt::Closed),
|
||||||
|
|
|
@ -3680,12 +3680,23 @@ pub enum ErrorType {
|
||||||
TypeExt,
|
TypeExt,
|
||||||
Polarity,
|
Polarity,
|
||||||
),
|
),
|
||||||
Function(Vec<ErrorType>, Box<ErrorType>, Box<ErrorType>),
|
Function(
|
||||||
|
Vec<ErrorType>,
|
||||||
|
Box<ErrorType>,
|
||||||
|
ErrorFunctionFx,
|
||||||
|
Box<ErrorType>,
|
||||||
|
),
|
||||||
Alias(Symbol, Vec<ErrorType>, Box<ErrorType>, AliasKind),
|
Alias(Symbol, Vec<ErrorType>, Box<ErrorType>, AliasKind),
|
||||||
Range(Vec<ErrorType>),
|
Range(Vec<ErrorType>),
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Hash)]
|
||||||
|
pub enum ErrorFunctionFx {
|
||||||
|
Pure,
|
||||||
|
Effectful,
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for ErrorType {
|
impl std::fmt::Debug for ErrorType {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// TODO remove clone
|
// TODO remove clone
|
||||||
|
@ -3731,7 +3742,7 @@ impl ErrorType {
|
||||||
.for_each(|(_, ts)| ts.iter().for_each(|t| t.add_names(taken)));
|
.for_each(|(_, ts)| ts.iter().for_each(|t| t.add_names(taken)));
|
||||||
ext.add_names(taken);
|
ext.add_names(taken);
|
||||||
}
|
}
|
||||||
Function(args, capt, ret) => {
|
Function(args, capt, _fx, ret) => {
|
||||||
args.iter().for_each(|t| t.add_names(taken));
|
args.iter().for_each(|t| t.add_names(taken));
|
||||||
capt.add_names(taken);
|
capt.add_names(taken);
|
||||||
ret.add_names(taken);
|
ret.add_names(taken);
|
||||||
|
@ -3817,7 +3828,7 @@ fn write_error_type_help(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Function(arguments, _closure, result) => {
|
Function(arguments, _closure, fx, result) => {
|
||||||
let write_parens = parens != Parens::Unnecessary;
|
let write_parens = parens != Parens::Unnecessary;
|
||||||
|
|
||||||
if write_parens {
|
if write_parens {
|
||||||
|
@ -3833,7 +3844,10 @@ fn write_error_type_help(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push_str(" -> ");
|
match fx {
|
||||||
|
ErrorFunctionFx::Pure => buf.push_str(" -> "),
|
||||||
|
ErrorFunctionFx::Effectful => buf.push_str(" => "),
|
||||||
|
}
|
||||||
|
|
||||||
write_error_type_help(interns, *result, buf, Parens::InFn);
|
write_error_type_help(interns, *result, buf, Parens::InFn);
|
||||||
|
|
||||||
|
@ -3967,7 +3981,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens:
|
||||||
buf.push(')');
|
buf.push(')');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Function(arguments, _closure, result) => {
|
Function(arguments, _closure, fx, result) => {
|
||||||
let write_parens = parens != Parens::Unnecessary;
|
let write_parens = parens != Parens::Unnecessary;
|
||||||
|
|
||||||
if write_parens {
|
if write_parens {
|
||||||
|
@ -3983,7 +3997,10 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.push_str(" -> ");
|
match fx {
|
||||||
|
ErrorFunctionFx::Pure => buf.push_str(" -> "),
|
||||||
|
ErrorFunctionFx::Effectful => buf.push_str(" => "),
|
||||||
|
}
|
||||||
|
|
||||||
write_debug_error_type_help(*result, buf, Parens::InFn);
|
write_debug_error_type_help(*result, buf, Parens::InFn);
|
||||||
|
|
||||||
|
|
|
@ -1406,7 +1406,6 @@ fn add_type_help<'a>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Content::Structure(FlatType::Func(args, closure_var, ret_var, _fx_var)) => {
|
Content::Structure(FlatType::Func(args, closure_var, ret_var, _fx_var)) => {
|
||||||
// [purity-inference] TODO: fx var
|
|
||||||
let is_toplevel = false; // or in any case, we cannot assume that we are
|
let is_toplevel = false; // or in any case, we cannot assume that we are
|
||||||
|
|
||||||
add_function_type(
|
add_function_type(
|
||||||
|
|
|
@ -1846,7 +1846,7 @@ fn describe_wanted_function(tipe: &ErrorType) -> DescribedFunction {
|
||||||
use ErrorType::*;
|
use ErrorType::*;
|
||||||
|
|
||||||
match tipe {
|
match tipe {
|
||||||
Function(args, _, _) => DescribedFunction::Arguments(args.len()),
|
Function(args, _, _, _) => DescribedFunction::Arguments(args.len()),
|
||||||
Alias(_, _, actual, AliasKind::Structural) => describe_wanted_function(actual),
|
Alias(_, _, actual, AliasKind::Structural) => describe_wanted_function(actual),
|
||||||
Alias(_, _, actual, AliasKind::Opaque) => {
|
Alias(_, _, actual, AliasKind::Opaque) => {
|
||||||
let tag = if matches!(
|
let tag = if matches!(
|
||||||
|
@ -2698,12 +2698,13 @@ fn to_doc_help<'b>(
|
||||||
use ErrorType::*;
|
use ErrorType::*;
|
||||||
|
|
||||||
match tipe {
|
match tipe {
|
||||||
Function(args, _, ret) => report_text::function(
|
Function(args, _, fx, ret) => report_text::function(
|
||||||
alloc,
|
alloc,
|
||||||
parens,
|
parens,
|
||||||
args.into_iter()
|
args.into_iter()
|
||||||
.map(|arg| to_doc_help(ctx, gen_usages, alloc, Parens::InFn, arg))
|
.map(|arg| to_doc_help(ctx, gen_usages, alloc, Parens::InFn, arg))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
fx,
|
||||||
to_doc_help(ctx, gen_usages, alloc, Parens::InFn, *ret),
|
to_doc_help(ctx, gen_usages, alloc, Parens::InFn, *ret),
|
||||||
),
|
),
|
||||||
Infinite => alloc.text("∞"),
|
Infinite => alloc.text("∞"),
|
||||||
|
@ -2940,7 +2941,7 @@ fn count_generated_name_usages<'a>(
|
||||||
stack.extend(tags.values().flatten().map(|t| (t, only_unseen)));
|
stack.extend(tags.values().flatten().map(|t| (t, only_unseen)));
|
||||||
ext_stack.push((ext, only_unseen));
|
ext_stack.push((ext, only_unseen));
|
||||||
}
|
}
|
||||||
Function(args, _lset, ret) => {
|
Function(args, _lset, _fx, ret) => {
|
||||||
stack.extend(args.iter().map(|t| (t, only_unseen)));
|
stack.extend(args.iter().map(|t| (t, only_unseen)));
|
||||||
stack.push((ret, only_unseen));
|
stack.push((ret, only_unseen));
|
||||||
}
|
}
|
||||||
|
@ -3115,7 +3116,7 @@ fn to_diff<'b>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Function(args1, _, ret1), Function(args2, _, ret2)) => {
|
(Function(args1, _, fx1, ret1), Function(args2, _, fx2, ret2)) => {
|
||||||
if args1.len() == args2.len() {
|
if args1.len() == args2.len() {
|
||||||
let mut status = Status::Similar;
|
let mut status = Status::Similar;
|
||||||
let arg_diff = diff_args(alloc, Parens::InFn, args1, args2);
|
let arg_diff = diff_args(alloc, Parens::InFn, args1, args2);
|
||||||
|
@ -3123,8 +3124,8 @@ fn to_diff<'b>(
|
||||||
status.merge(arg_diff.status);
|
status.merge(arg_diff.status);
|
||||||
status.merge(ret_diff.status);
|
status.merge(ret_diff.status);
|
||||||
|
|
||||||
let left = report_text::function(alloc, parens, arg_diff.left, ret_diff.left);
|
let left = report_text::function(alloc, parens, arg_diff.left, fx1, ret_diff.left);
|
||||||
let right = report_text::function(alloc, parens, arg_diff.right, ret_diff.right);
|
let right = report_text::function(alloc, parens, arg_diff.right, fx2, ret_diff.right);
|
||||||
let mut left_able = arg_diff.left_able;
|
let mut left_able = arg_diff.left_able;
|
||||||
left_able.extend(ret_diff.left_able);
|
left_able.extend(ret_diff.left_able);
|
||||||
let mut right_able = arg_diff.right_able;
|
let mut right_able = arg_diff.right_able;
|
||||||
|
@ -3713,9 +3714,10 @@ fn should_show_diff(t1: &ErrorType, t2: &ErrorType) -> bool {
|
||||||
.any(|(p1, p2)| should_show_diff(p1, p2))
|
.any(|(p1, p2)| should_show_diff(p1, p2))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(Function(params1, ret1, l1), Function(params2, ret2, l2)) => {
|
(Function(params1, ret1, fx1, l1), Function(params2, ret2, fx2, l2)) => {
|
||||||
if params1.len() != params2.len()
|
if params1.len() != params2.len()
|
||||||
|| should_show_diff(ret1, ret2)
|
|| should_show_diff(ret1, ret2)
|
||||||
|
|| fx1 != fx2
|
||||||
|| should_show_diff(l1, l2)
|
|| should_show_diff(l1, l2)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -3777,8 +3779,8 @@ fn should_show_diff(t1: &ErrorType, t2: &ErrorType) -> bool {
|
||||||
| (_, TagUnion(_, _, _))
|
| (_, TagUnion(_, _, _))
|
||||||
| (RecursiveTagUnion(_, _, _, _), _)
|
| (RecursiveTagUnion(_, _, _, _), _)
|
||||||
| (_, RecursiveTagUnion(_, _, _, _))
|
| (_, RecursiveTagUnion(_, _, _, _))
|
||||||
| (Function(_, _, _), _)
|
| (Function(_, _, _, _), _)
|
||||||
| (_, Function(_, _, _)) => true,
|
| (_, Function(_, _, _, _)) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4236,7 +4238,7 @@ mod report_text {
|
||||||
use crate::report::{Annotation, RocDocAllocator, RocDocBuilder};
|
use crate::report::{Annotation, RocDocAllocator, RocDocBuilder};
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_types::pretty_print::Parens;
|
use roc_types::pretty_print::Parens;
|
||||||
use roc_types::types::{ErrorType, RecordField, TypeExt};
|
use roc_types::types::{ErrorFunctionFx, ErrorType, RecordField, TypeExt};
|
||||||
use ven_pretty::DocAllocator;
|
use ven_pretty::DocAllocator;
|
||||||
|
|
||||||
fn with_parens<'b>(
|
fn with_parens<'b>(
|
||||||
|
@ -4250,11 +4252,15 @@ mod report_text {
|
||||||
alloc: &'b RocDocAllocator<'b>,
|
alloc: &'b RocDocAllocator<'b>,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
args: Vec<RocDocBuilder<'b>>,
|
args: Vec<RocDocBuilder<'b>>,
|
||||||
|
fx: ErrorFunctionFx,
|
||||||
ret: RocDocBuilder<'b>,
|
ret: RocDocBuilder<'b>,
|
||||||
) -> RocDocBuilder<'b> {
|
) -> RocDocBuilder<'b> {
|
||||||
let function_doc = alloc.concat([
|
let function_doc = alloc.concat([
|
||||||
alloc.intersperse(args, alloc.reflow(", ")),
|
alloc.intersperse(args, alloc.reflow(", ")),
|
||||||
alloc.reflow(" -> "),
|
match fx {
|
||||||
|
ErrorFunctionFx::Pure => alloc.text(" -> "),
|
||||||
|
ErrorFunctionFx::Effectful => alloc.text(" => "),
|
||||||
|
},
|
||||||
ret,
|
ret,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -4820,7 +4826,7 @@ fn type_problem_to_pretty<'b>(
|
||||||
rigid_able_vs_different_flex_able(x, abilities, other_abilities)
|
rigid_able_vs_different_flex_able(x, abilities, other_abilities)
|
||||||
}
|
}
|
||||||
RigidVar(y) | RigidAbleVar(y, _) => bad_double_rigid(x, y),
|
RigidVar(y) | RigidAbleVar(y, _) => bad_double_rigid(x, y),
|
||||||
Function(_, _, _) => rigid_able_vs_concrete(x, alloc.reflow("a function value")),
|
Function(_, _, _, _) => rigid_able_vs_concrete(x, alloc.reflow("a function value")),
|
||||||
Record(_, _) => rigid_able_vs_concrete(x, alloc.reflow("a record value")),
|
Record(_, _) => rigid_able_vs_concrete(x, alloc.reflow("a record value")),
|
||||||
Tuple(_, _) => rigid_able_vs_concrete(x, alloc.reflow("a tuple value")),
|
Tuple(_, _) => rigid_able_vs_concrete(x, alloc.reflow("a tuple value")),
|
||||||
TagUnion(_, _, _) | RecursiveTagUnion(_, _, _, _) => {
|
TagUnion(_, _, _) | RecursiveTagUnion(_, _, _, _) => {
|
||||||
|
@ -4909,7 +4915,7 @@ fn type_problem_to_pretty<'b>(
|
||||||
bad_rigid_var(x, msg)
|
bad_rigid_var(x, msg)
|
||||||
}
|
}
|
||||||
RigidVar(y) | RigidAbleVar(y, _) => bad_double_rigid(x, y),
|
RigidVar(y) | RigidAbleVar(y, _) => bad_double_rigid(x, y),
|
||||||
Function(_, _, _) => bad_rigid_var(x, alloc.reflow("a function value")),
|
Function(_, _, _, _) => bad_rigid_var(x, alloc.reflow("a function value")),
|
||||||
Record(_, _) => bad_rigid_var(x, alloc.reflow("a record value")),
|
Record(_, _) => bad_rigid_var(x, alloc.reflow("a record value")),
|
||||||
Tuple(_, _) => bad_rigid_var(x, alloc.reflow("a tuple value")),
|
Tuple(_, _) => bad_rigid_var(x, alloc.reflow("a tuple value")),
|
||||||
TagUnion(_, _, _) | RecursiveTagUnion(_, _, _, _) => {
|
TagUnion(_, _, _) | RecursiveTagUnion(_, _, _, _) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue