diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 4a1c6b1f23..cbf8649aaf 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -4212,6 +4212,7 @@ fn convert_tag_union<'a>( ))); } }; + match variant { Never => unreachable!( "The `[]` type has no constructors, source var {:?}", @@ -4253,7 +4254,13 @@ fn convert_tag_union<'a>( .unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err)); // even though this was originally a Tag, we treat it as a Struct from now on - let stmt = Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole); + let stmt = if let [only_field] = field_symbols { + let mut hole = hole.clone(); + substitute_in_exprs(env.arena, &mut hole, assigned, *only_field); + hole + } else { + Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole) + }; let iter = field_symbols_temp.into_iter().map(|(_, _, data)| data); assign_to_symbols(env, procs, layout_cache, iter, stmt) @@ -4480,6 +4487,7 @@ fn tag_union_to_function<'a>( ) -> Stmt<'a> { let mut loc_pattern_args = vec![]; let mut loc_expr_args = vec![]; + for arg_var in argument_variables { let arg_symbol = env.unique_symbol(); @@ -4490,12 +4498,14 @@ fn tag_union_to_function<'a>( loc_pattern_args.push((arg_var, loc_pattern)); loc_expr_args.push((arg_var, loc_expr)); } + let loc_body = Located::at_zero(roc_can::expr::Expr::Tag { variant_var: return_variable, name: tag_name, arguments: loc_expr_args, ext_var, }); + let inserted = procs.insert_anonymous( env, proc_symbol, @@ -4506,8 +4516,9 @@ fn tag_union_to_function<'a>( return_variable, layout_cache, ); + match inserted { - Ok(layout) => { + Ok(_layout) => { // only need to construct closure data let full_layout = return_on_layout_error!(env, layout_cache.from_var(env.arena, whole_var, env.subs)); diff --git a/compiler/test_gen/src/gen_tags.rs b/compiler/test_gen/src/gen_tags.rs index 81c5500ed1..a16ba1a6af 100644 --- a/compiler/test_gen/src/gen_tags.rs +++ b/compiler/test_gen/src/gen_tags.rs @@ -996,7 +996,6 @@ fn applied_tag_function() { } #[test] -#[ignore] fn applied_tag_function_result() { assert_evals_to!( indoc!( @@ -1016,7 +1015,6 @@ fn applied_tag_function_result() { } #[test] -#[ignore] fn applied_tag_function_linked_list() { assert_evals_to!( indoc!( diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index 3f88aff3bd..7a7ca125a0 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -1270,11 +1270,11 @@ fn unify_function_or_tag_union_and_func( pool: &mut Pool, ctx: &Context, tag_name: &TagName, - _tag_symbol: Symbol, + tag_symbol: Symbol, tag_ext: Variable, function_arguments: &[Variable], function_return: Variable, - _function_lambda_set: Variable, + function_lambda_set: Variable, left: bool, ) -> Outcome { use FlatType::*; @@ -1287,12 +1287,40 @@ fn unify_function_or_tag_union_and_func( let new_tag_union_var = fresh(subs, pool, ctx, content); - let problems = if left { + let mut problems = if left { unify_pool(subs, pool, new_tag_union_var, function_return) } else { unify_pool(subs, pool, function_return, new_tag_union_var) }; + { + let lambda_set_ext = subs.fresh_unnamed_flex_var(); + + let mut closure_tags = MutMap::with_capacity_and_hasher(1, default_hasher()); + closure_tags.insert(TagName::Closure(tag_symbol), vec![]); + + let lambda_set_content = Structure(TagUnion(closure_tags, lambda_set_ext)); + + let tag_lambda_set = register( + subs, + Descriptor { + content: lambda_set_content, + rank: ctx.first_desc.rank.min(ctx.second_desc.rank), + mark: Mark::NONE, + copy: OptVariable::NONE, + }, + pool, + ); + + let closure_problems = if left { + unify_pool(subs, pool, tag_lambda_set, function_lambda_set) + } else { + unify_pool(subs, pool, function_lambda_set, tag_lambda_set) + }; + + problems.extend(closure_problems); + } + if problems.is_empty() { let desc = if left { subs.get(ctx.second)