From 2079a64cb772314f6ff23c8e582b03d0c6dcc929 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Wed, 22 Jun 2022 12:36:37 -0400 Subject: [PATCH] Make sure to unwrap non-nullable unwrapped unions directly in alias analysis Non-nullable unwrapped tag unions are represented directly as the type of their singleton variant in morphic. Other recursive tag unions are something like `(heap_cell, union [A, B ()])` for recursive union `[A, B ()]`, but a non-nullable unwrapped tag union `[ Foo Str ]` is represented directly as the tuple `(Str )`. Make sure we don't try to unwrap a non-existent heap cell and union data for such type representations. Closes #3261 --- compiler/alias_analysis/src/lib.rs | 18 +++++------------- compiler/test_gen/src/gen_tags.rs | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/compiler/alias_analysis/src/lib.rs b/compiler/alias_analysis/src/lib.rs index 91e331f8d5..754f271c50 100644 --- a/compiler/alias_analysis/src/lib.rs +++ b/compiler/alias_analysis/src/lib.rs @@ -573,7 +573,8 @@ fn build_recursive_tuple_type( let mut field_types = Vec::new(); for field in layouts.iter() { - field_types.push(layout_spec_help(builder, field, when_recursive)?); + let type_id = layout_spec_help(builder, field, when_recursive)?; + field_types.push(type_id); } builder.add_tuple_type(&field_types) @@ -1617,18 +1618,9 @@ fn expr_spec<'a>( let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes(); let type_name = TypeName(&type_name_bytes); - // a tuple ( cell, union { ... } ) - let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?; - - // decompose - let heap_cell = builder.add_get_tuple_field(block, union_id, TAG_CELL_INDEX)?; - let union_data = builder.add_get_tuple_field(block, union_id, TAG_DATA_INDEX)?; - - // we're reading from this value, so touch the heap cell - builder.add_touch(block, heap_cell)?; - - // next, unwrap the union at the tag id that we've got - let variant_id = builder.add_unwrap_union(block, union_data, *tag_id as u32)?; + // the unwrapped recursive tag variant + let variant_id = + builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?; builder.add_get_tuple_field(block, variant_id, index) } diff --git a/compiler/test_gen/src/gen_tags.rs b/compiler/test_gen/src/gen_tags.rs index 4855c4b208..a2de31653d 100644 --- a/compiler/test_gen/src/gen_tags.rs +++ b/compiler/test_gen/src/gen_tags.rs @@ -1703,3 +1703,24 @@ fn issue_2900_unreachable_pattern() { true // ignore type errors ) } + +#[test] +#[cfg(any(feature = "gen-llvm"))] +fn issue_3261_non_nullable_unwrapped_recursive_union_at_index() { + assert_evals_to!( + indoc!( + r#" + Named : [Named Str (List Named)] + + foo : Named + foo = Named "outer" [Named "inner" []] + + Named name outerList = foo + + {name, outerList}.name + "# + ), + RocStr::from("outer"), + RocStr + ) +}