Dereference small (non recursive) tag unions before storing them elsewhere

Closes #2290
This commit is contained in:
ayazhafiz 2021-12-27 23:01:56 -06:00
parent 2c25bac695
commit f52cca40b5
2 changed files with 31 additions and 0 deletions

View file

@ -1394,6 +1394,18 @@ fn build_wrapped_tag<'a, 'ctx, 'env>(
); );
field_vals.push(ptr); 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 { } else {
// this check fails for recursive tag unions, but can be helpful while debugging // this check fails for recursive tag unions, but can be helpful while debugging
// debug_assert_eq!(tag_field_layout, val_layout); // debug_assert_eq!(tag_field_layout, val_layout);

View file

@ -1243,3 +1243,22 @@ fn tag_must_be_its_own_type() {
i64 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
)
}