diff --git a/crates/plotnik-lib/src/analyze/type_check/infer.rs b/crates/plotnik-lib/src/analyze/type_check/infer.rs index 36eae1f0..cbe08e3a 100644 --- a/crates/plotnik-lib/src/analyze/type_check/infer.rs +++ b/crates/plotnik-lib/src/analyze/type_check/infer.rs @@ -348,9 +348,16 @@ impl<'a, 'd> InferenceVisitor<'a, 'd> { } /// Determines if an expression creates a scope boundary when captured. + /// + /// When captured, these expressions produce structured values (not nodes): + /// - Sequences/alternations: produce structs/enums from their internal captures + /// - Refs: produce whatever the called definition returns (struct if it has captures) + /// + /// This only affects captured expressions. Uncaptured refs remain transparent + /// (their captures bubble up) because this check only runs in `infer_captured_expr`. fn inner_creates_scope(inner: &Expr) -> bool { match inner { - Expr::SeqExpr(_) | Expr::AltExpr(_) => true, + Expr::SeqExpr(_) | Expr::AltExpr(_) | Expr::Ref(_) => true, Expr::QuantifiedExpr(q) => { // Look through quantifier to the actual expression q.inner() diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_nested_capture.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_nested_capture.snap index b2e77d44..e1849b36 100644 --- a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_nested_capture.snap +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__definitions_nested_capture.snap @@ -21,15 +21,14 @@ S8 "parent" [type_defs] T0 = T1 = Struct M0:1 ; { name } -T2 = Struct M1:2 ; { name, item } +T2 = Struct M1:1 ; { item } T3 = ArrayStar(T2) ; T2* -T4 = Struct M3:1 ; { items } +T4 = Struct M2:1 ; { items } [type_members] M0: S1 → T0 ; name: -M1: S1 → T0 ; name: -M2: S2 → T0 ; item: -M3: S3 → T3 ; items: T3 +M1: S2 → T1 ; item: Inner +M2: S3 → T3 ; items: T3 [type_names] N0: S4 → T1 ; Inner @@ -57,14 +56,14 @@ Outer: 14 ! (parent) 15 15 ε [Arr] 17 17 ε 41, 29 - 19 ε [EndArr Set(M3)] 21 + 19 ε [EndArr Set(M2)] 21 21 △ 27 22 ε [EndObj Push] 24 24 ε 47, 19 26 ▶ 27 ε [EndObj] 26 - 29 ε [EndArr Set(M3)] 27 - 31 ε [Set(M2)] 22 + 29 ε [EndArr Set(M2)] 27 + 31 ε [Set(M1)] 22 33 ! (Inner) 01 : 31 34 ε [Obj] 33 36 ▷ 39 diff --git a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_sequence_in_called_def.snap b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_sequence_in_called_def.snap index 1b670791..0d4b571f 100644 --- a/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_sequence_in_called_def.snap +++ b/crates/plotnik-lib/src/emit/snapshots/plotnik_lib__emit__codegen_tests__quantifiers_sequence_in_called_def.snap @@ -22,15 +22,14 @@ S8 "parent" [type_defs] T0 = T1 = Struct M0:1 ; { name } -T2 = Struct M1:2 ; { name, item } +T2 = Struct M1:1 ; { item } T3 = ArrayStar(T2) ; T2* -T4 = Struct M3:1 ; { items } +T4 = Struct M2:1 ; { items } [type_members] M0: S1 → T0 ; name: -M1: S1 → T0 ; name: -M2: S2 → T0 ; item: -M3: S3 → T3 ; items: T3 +M1: S2 → T1 ; item: Item +M2: S3 → T3 ; items: T3 [type_names] N0: S4 → T1 ; Item @@ -68,8 +67,8 @@ Test: 23 ε 46, 28 25 ▶ 26 ε [EndObj] 25 - 28 ε [EndArr Set(M3)] 26 - 30 ε [Set(M2)] 21 + 28 ε [EndArr Set(M2)] 26 + 30 ε [Set(M1)] 21 32 ! (Item) 01 : 30 33 ε [Obj] 32 35 ▷ 38