Skip to content

Commit

Permalink
Add fx to ErrorType
Browse files Browse the repository at this point in the history
  • Loading branch information
agu-z committed Oct 21, 2024
1 parent d12fb71 commit 3d2b622
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 30 deletions.
4 changes: 2 additions & 2 deletions crates/compiler/load/tests/test_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5419,9 +5419,9 @@ mod test_reporting {
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
"###
Expand Down
6 changes: 3 additions & 3 deletions crates/compiler/lower_params/src/type_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ pub fn remove_module_param_arguments(
drop_last_argument(expected);

if let (
ErrorType::Function(found_args, _, _),
ErrorType::Function(expected_args, _, _),
ErrorType::Function(found_args, _, _, _),
ErrorType::Function(expected_args, _, _, _),
) = (found, expected)
{
if found_args.len() > expected_args.len() {
Expand Down Expand Up @@ -193,7 +193,7 @@ fn remove_for_reason(

fn drop_last_argument(err_type: &mut ErrorType) {
match err_type {
ErrorType::Function(arguments, _, _) => {
ErrorType::Function(arguments, _, _, _) => {
arguments.pop();
}
// Irrelevant
Expand Down
24 changes: 19 additions & 5 deletions crates/compiler/types/src/subs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![deny(unsafe_op_in_unsafe_fn)]
use crate::types::{
name_type_var, AbilitySet, AliasKind, ErrorType, ExtImplicitOpenness, Polarity, RecordField,
RecordFieldsError, TupleElemsError, TypeExt, Uls,
name_type_var, AbilitySet, AliasKind, ErrorFunctionFx, ErrorType, ExtImplicitOpenness,
Polarity, RecordField, RecordFieldsError, TupleElemsError, TypeExt, Uls,
};
use crate::unification_table::{self, UnificationTable};
use roc_collections::all::{FnvMap, ImMap, ImSet, MutSet, SendMap};
Expand Down Expand Up @@ -4142,7 +4142,7 @@ fn flat_type_to_err_type(
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
.into_iter()
.map(|index| {
Expand All @@ -4153,9 +4153,23 @@ fn flat_type_to_err_type(

let ret = var_to_err_type(subs, state, ret_var, Polarity::Pos);
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), Box::new(ret))
ErrorType::Function(args, Box::new(closure), fx, Box::new(ret))
}

EmptyRecord => ErrorType::Record(SendMap::default(), TypeExt::Closed),
Expand Down
29 changes: 23 additions & 6 deletions crates/compiler/types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3677,12 +3677,23 @@ pub enum ErrorType {
TypeExt,
Polarity,
),
Function(Vec<ErrorType>, Box<ErrorType>, Box<ErrorType>),
Function(
Vec<ErrorType>,
Box<ErrorType>,
ErrorFunctionFx,
Box<ErrorType>,
),
Alias(Symbol, Vec<ErrorType>, Box<ErrorType>, AliasKind),
Range(Vec<ErrorType>),
Error,
}

#[derive(PartialEq, Eq, Clone, Hash)]
pub enum ErrorFunctionFx {
Pure,
Effectful,
}

impl std::fmt::Debug for ErrorType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// TODO remove clone
Expand Down Expand Up @@ -3728,7 +3739,7 @@ impl ErrorType {
.for_each(|(_, ts)| ts.iter().for_each(|t| t.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));
capt.add_names(taken);
ret.add_names(taken);
Expand Down Expand Up @@ -3814,7 +3825,7 @@ fn write_error_type_help(
}
}
}
Function(arguments, _closure, result) => {
Function(arguments, _closure, fx, result) => {
let write_parens = parens != Parens::Unnecessary;

if write_parens {
Expand All @@ -3830,7 +3841,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);

Expand Down Expand Up @@ -3964,7 +3978,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens:
buf.push(')');
}
}
Function(arguments, _closure, result) => {
Function(arguments, _closure, fx, result) => {
let write_parens = parens != Parens::Unnecessary;

if write_parens {
Expand All @@ -3980,7 +3994,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);

Expand Down
1 change: 0 additions & 1 deletion crates/glue/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,6 @@ fn add_type_help<'a>(
}
},
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

add_function_type(
Expand Down
32 changes: 19 additions & 13 deletions crates/reporting/src/error/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1809,7 +1809,7 @@ fn describe_wanted_function(tipe: &ErrorType) -> DescribedFunction {
use ErrorType::*;

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::Opaque) => {
let tag = if matches!(
Expand Down Expand Up @@ -2657,12 +2657,13 @@ fn to_doc_help<'b>(
use ErrorType::*;

match tipe {
Function(args, _, ret) => report_text::function(
Function(args, _, fx, ret) => report_text::function(
alloc,
parens,
args.into_iter()
.map(|arg| to_doc_help(ctx, gen_usages, alloc, Parens::InFn, arg))
.collect(),
fx,
to_doc_help(ctx, gen_usages, alloc, Parens::InFn, *ret),
),
Infinite => alloc.text("∞"),
Expand Down Expand Up @@ -2899,7 +2900,7 @@ fn count_generated_name_usages<'a>(
stack.extend(tags.values().flatten().map(|t| (t, 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.push((ret, only_unseen));
}
Expand Down Expand Up @@ -3074,16 +3075,16 @@ fn to_diff<'b>(
}
}

(Function(args1, _, ret1), Function(args2, _, ret2)) => {
(Function(args1, _, fx1, ret1), Function(args2, _, fx2, ret2)) => {
if args1.len() == args2.len() {
let mut status = Status::Similar;
let arg_diff = diff_args(alloc, Parens::InFn, args1, args2);
let ret_diff = to_diff(alloc, Parens::InFn, *ret1, *ret2);
status.merge(arg_diff.status);
status.merge(ret_diff.status);

let left = report_text::function(alloc, parens, arg_diff.left, ret_diff.left);
let right = report_text::function(alloc, parens, arg_diff.right, ret_diff.right);
let left = report_text::function(alloc, parens, arg_diff.left, fx1, ret_diff.left);
let right = report_text::function(alloc, parens, arg_diff.right, fx2, ret_diff.right);
let mut left_able = arg_diff.left_able;
left_able.extend(ret_diff.left_able);
let mut right_able = arg_diff.right_able;
Expand Down Expand Up @@ -3672,9 +3673,10 @@ fn should_show_diff(t1: &ErrorType, t2: &ErrorType) -> bool {
.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()
|| should_show_diff(ret1, ret2)
|| fx1 != fx2
|| should_show_diff(l1, l2)
{
return true;
Expand Down Expand Up @@ -3736,8 +3738,8 @@ fn should_show_diff(t1: &ErrorType, t2: &ErrorType) -> bool {
| (_, TagUnion(_, _, _))
| (RecursiveTagUnion(_, _, _, _), _)
| (_, RecursiveTagUnion(_, _, _, _))
| (Function(_, _, _), _)
| (_, Function(_, _, _)) => true,
| (Function(_, _, _, _), _)
| (_, Function(_, _, _, _)) => true,
}
}

Expand Down Expand Up @@ -4195,7 +4197,7 @@ mod report_text {
use crate::report::{Annotation, RocDocAllocator, RocDocBuilder};
use roc_module::ident::Lowercase;
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;

fn with_parens<'b>(
Expand All @@ -4209,11 +4211,15 @@ mod report_text {
alloc: &'b RocDocAllocator<'b>,
parens: Parens,
args: Vec<RocDocBuilder<'b>>,
fx: ErrorFunctionFx,
ret: RocDocBuilder<'b>,
) -> RocDocBuilder<'b> {
let function_doc = alloc.concat([
alloc.intersperse(args, alloc.reflow(", ")),
alloc.reflow(" -> "),
match fx {
ErrorFunctionFx::Pure => alloc.text(" -> "),
ErrorFunctionFx::Effectful => alloc.text(" => "),
},
ret,
]);

Expand Down Expand Up @@ -4779,7 +4785,7 @@ fn type_problem_to_pretty<'b>(
rigid_able_vs_different_flex_able(x, abilities, other_abilities)
}
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")),
Tuple(_, _) => rigid_able_vs_concrete(x, alloc.reflow("a tuple value")),
TagUnion(_, _, _) | RecursiveTagUnion(_, _, _, _) => {
Expand Down Expand Up @@ -4868,7 +4874,7 @@ fn type_problem_to_pretty<'b>(
bad_rigid_var(x, msg)
}
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")),
Tuple(_, _) => bad_rigid_var(x, alloc.reflow("a tuple value")),
TagUnion(_, _, _) | RecursiveTagUnion(_, _, _, _) => {
Expand Down

0 comments on commit 3d2b622

Please sign in to comment.