diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index cf0b05a369..94f3ea89ec 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -1394,6 +1394,18 @@ fn build_wrapped_tag<'a, 'ctx, 'env>( ); field_vals.push(ptr); + } else if matches!( + tag_field_layout, + Layout::Union(UnionLayout::NonRecursive(_)) + ) { + debug_assert!(val.is_pointer_value()); + + // We store non-recursive unions without any indirection. + let reified = env + .builder + .build_load(val.into_pointer_value(), "load_non_recursive"); + + field_vals.push(reified); } else { // this check fails for recursive tag unions, but can be helpful while debugging // debug_assert_eq!(tag_field_layout, val_layout); diff --git a/compiler/test_gen/src/gen_tags.rs b/compiler/test_gen/src/gen_tags.rs index b4dc57e4dd..f396534be8 100644 --- a/compiler/test_gen/src/gen_tags.rs +++ b/compiler/test_gen/src/gen_tags.rs @@ -1243,3 +1243,22 @@ fn tag_must_be_its_own_type() { i64 ); } + +#[test] +#[cfg(any(feature = "gen-llvm"))] +fn recursive_tag_union_into_flat_tag_union() { + // Comprehensive test for correctness in cli/tests/repl_eval + assert_evals_to!( + indoc!( + r#" + Item : [ Shallow [ L Str, R Str ], Deep Item ] + i : Item + i = Deep (Shallow (R "woo")) + i + "# + ), + 0, + usize, + |_| 0 + ) +}