diff --git a/cli/src/repl/eval.rs b/cli/src/repl/eval.rs index 36cb52723a..5f68906443 100644 --- a/cli/src/repl/eval.rs +++ b/cli/src/repl/eval.rs @@ -140,6 +140,9 @@ fn jit_to_ast_help<'a>( single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), payload_vars) } + Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => { + single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), &[]) + } other => { unreachable!( "Something had a Struct layout, but instead of a Record or TagUnion type, it had: {:?}", @@ -313,6 +316,9 @@ fn ptr_to_ast<'a>( let (tag_name, payload_vars) = tags.iter().next().unwrap(); single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), payload_vars) } + Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => { + single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), &[]) + } Content::Structure(FlatType::EmptyRecord) => { struct_to_ast(env, ptr, &[], &MutMap::default()) } diff --git a/compiler/mono/src/layout.rs b/compiler/mono/src/layout.rs index 2c7518b185..620f700a90 100644 --- a/compiler/mono/src/layout.rs +++ b/compiler/mono/src/layout.rs @@ -423,6 +423,12 @@ impl<'a, 'b> Env<'a, 'b> { self.seen.insert(var) } + + fn remove_seen(&mut self, var: Variable) -> bool { + let var = self.subs.get_root_key_without_compacting(var); + + self.seen.remove(&var) + } } impl<'a> Layout<'a> { @@ -1248,6 +1254,8 @@ fn layout_from_flat_type<'a>( UnionLayout::Recursive(tag_layouts.into_bump_slice()) }; + env.remove_seen(rec_var); + Ok(Layout::Union(union_layout)) } EmptyTagUnion => { diff --git a/compiler/types/src/pretty_print.rs b/compiler/types/src/pretty_print.rs index b9d5ad850a..2b9ac83553 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -595,6 +595,11 @@ pub fn chase_ext_tag_union( chase_ext_tag_union(subs, ext_var, fields) } + Content::Structure(FunctionOrTagUnion(tag_name, _, ext_var)) => { + fields.push((tag_name, vec![])); + + chase_ext_tag_union(subs, ext_var, fields) + } Content::Alias(_, _, var) => chase_ext_tag_union(subs, var, fields), content => Err((var, content)), diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index 9e8a56da3f..6eee91b429 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -1051,13 +1051,14 @@ fn unify_flat_type( } (RecursiveTagUnion(recursion_var, tags1, ext1), FunctionOrTagUnion(tag_name, _, ext2)) => { + // this never happens in type-correct programs, but may happen if there is a type error debug_assert!(is_recursion_var(subs, *recursion_var)); - let union1 = gather_tags(subs, tags1.clone(), *ext1); - let mut tags2 = MutMap::default(); tags2.insert(tag_name.clone(), vec![]); - let union2 = gather_tags(subs, tags2, *ext2); + + let union1 = gather_tags(subs, tags1.clone(), *ext1); + let union2 = gather_tags(subs, tags2.clone(), *ext2); unify_tag_union( subs, @@ -1074,12 +1075,13 @@ fn unify_flat_type( let mut tags1 = MutMap::default(); tags1.insert(tag_name.clone(), vec![]); - let union1 = gather_tags(subs, tags1, *ext1); + let union1 = gather_tags(subs, tags1.clone(), *ext1); let union2 = gather_tags(subs, tags2.clone(), *ext2); unify_tag_union_not_recursive_recursive(subs, pool, ctx, union1, union2, *recursion_var) } + (other1, other2) => mismatch!( "Trying to unify two flat types that are incompatible: {:?} ~ {:?}", other1,