diff --git a/compiler/mono/src/decision_tree.rs b/compiler/mono/src/decision_tree.rs index 7e9395e781..04d25e0b78 100644 --- a/compiler/mono/src/decision_tree.rs +++ b/compiler/mono/src/decision_tree.rs @@ -1036,8 +1036,8 @@ fn path_to_expr_help<'a>( let mut it = instructions.iter().peekable(); while let Some(PathInstruction { index, tag_id }) = it.next() { - match Wrapped::opt_from_layout(&layout) { - None => { + match Wrapped::is_indexable(&layout) { + false => { // this MUST be an index into a single-element (hence unwrapped) record debug_assert_eq!(*index, 0, "{:?}", &layout); @@ -1063,7 +1063,7 @@ fn path_to_expr_help<'a>( break; } - Some(wrapped) => { + true => { let index = *index; let (inner_layout, inner_expr) = match layout { @@ -1078,6 +1078,7 @@ fn path_to_expr_help<'a>( (union_layout.layout_at(*tag_id as u8, index as usize), expr) } Layout::Struct(field_layouts) => { + let wrapped = Wrapped::opt_from_layout(&layout).unwrap(); debug_assert!(field_layouts.len() > 1); debug_assert_eq!(wrapped, Wrapped::RecordOrSingleTagUnion); diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 5652fe3212..d840663142 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -1032,6 +1032,17 @@ impl Wrapped { } } + pub fn is_indexable(layout: &Layout<'_>) -> bool { + match layout { + Layout::Struct(fields) => match fields.len() { + _ => true, + }, + + Layout::Union(variant) => true, + _ => false, + } + } + pub fn opt_from_layout(layout: &Layout<'_>) -> Option { match layout { Layout::Struct(fields) => match fields.len() { @@ -1056,6 +1067,7 @@ impl Wrapped { NonNullableUnwrapped(_) => Some(Wrapped::LikeARoseTree), NullableWrapped { .. } | NullableUnwrapped { .. } => { + todo!(); Some(Wrapped::MultiTagUnion) } } @@ -2133,6 +2145,8 @@ fn specialize_external<'a>( match closure_layout.layout_for_member(proc_name) { ClosureRepresentation::Union { tag_layout: field_layouts, + union_layout, + tag_id, .. } => { debug_assert_eq!(field_layouts.len() - 1, captured.len()); @@ -2143,11 +2157,11 @@ fn specialize_external<'a>( index += 1; // TODO therefore should the wrapped here not be RecordOrSingleTagUnion? - let expr = Expr::AccessAtIndex { - index: index as _, - field_layouts, + let expr = Expr::CoerceToTagId { + tag_id, structure: Symbol::ARG_CLOSURE, - wrapped, + index: index as _, + union_layout, }; let layout = field_layouts[index]; @@ -4074,21 +4088,17 @@ fn construct_closure_data<'a>( tag_layout: _, union_size, tag_name, + union_layout, } => { let tag_id_symbol = env.unique_symbol(); let mut tag_symbols = Vec::with_capacity_in(symbols.len() + 1, env.arena); tag_symbols.push(tag_id_symbol); tag_symbols.extend(symbols); - let tag_layout = match lambda_set.runtime_representation() { - Layout::Union(inner) => inner, - _ => unreachable!(), - }; - let expr1 = Expr::Literal(Literal::Int(tag_id as i128)); let expr2 = Expr::Tag { tag_id, - tag_layout, + tag_layout: union_layout, union_size, tag_name, arguments: tag_symbols.into_bump_slice(), diff --git a/compiler/mono/src/layout.rs b/compiler/mono/src/layout.rs index 7fdb9754d6..05e02cf9ca 100644 --- a/compiler/mono/src/layout.rs +++ b/compiler/mono/src/layout.rs @@ -200,6 +200,7 @@ pub enum ClosureRepresentation<'a> { tag_name: TagName, tag_id: u8, union_size: u8, + union_layout: UnionLayout<'a>, }, /// the representation is anything but a union Other(Layout<'a>), @@ -241,6 +242,7 @@ impl<'a> LambdaSet<'a> { tag_id: index as u8, tag_layout: tags[index], tag_name: TagName::Closure(function_symbol), + union_layout: *union, } } UnionLayout::Recursive(_) => todo!("recursive closures"), diff --git a/compiler/test_mono/generated/specialize_closures.txt b/compiler/test_mono/generated/specialize_closures.txt index b67e0561b7..5534042fa3 100644 --- a/compiler/test_mono/generated/specialize_closures.txt +++ b/compiler/test_mono/generated/specialize_closures.txt @@ -22,13 +22,13 @@ procedure Test.1 (Test.2, Test.3): procedure Test.7 (Test.10, #Attr.12): - let Test.4 = Index 1 #Attr.12; + let Test.4 = CoerceToTagId (Id 0) (Index 1) #Attr.12; let Test.29 = CallByName Num.24 Test.10 Test.4; ret Test.29; procedure Test.8 (Test.11, #Attr.12): - let Test.6 = Index 2 #Attr.12; - let Test.5 = Index 1 #Attr.12; + let Test.6 = CoerceToTagId (Id 1) (Index 2) #Attr.12; + let Test.5 = CoerceToTagId (Id 1) (Index 1) #Attr.12; if Test.6 then let Test.24 = CallByName Num.26 Test.11 Test.5; ret Test.24; diff --git a/compiler/test_mono/generated/specialize_lowlevel.txt b/compiler/test_mono/generated/specialize_lowlevel.txt index 6f36920266..cd81b26370 100644 --- a/compiler/test_mono/generated/specialize_lowlevel.txt +++ b/compiler/test_mono/generated/specialize_lowlevel.txt @@ -7,12 +7,12 @@ procedure Num.26 (#Attr.2, #Attr.3): ret Test.21; procedure Test.6 (Test.8, #Attr.12): - let Test.4 = Index 1 #Attr.12; + let Test.4 = CoerceToTagId (Id 0) (Index 1) #Attr.12; let Test.25 = CallByName Num.24 Test.8 Test.4; ret Test.25; procedure Test.7 (Test.9, #Attr.12): - let Test.5 = Index 1 #Attr.12; + let Test.5 = CoerceToTagId (Id 1) (Index 1) #Attr.12; let Test.20 = CallByName Num.26 Test.9 Test.5; ret Test.20;