@@ -11,7 +11,7 @@ use crate::bytecode::ir::EffectIR;
1111use crate :: parser:: ast:: { self , Expr } ;
1212
1313use super :: Compiler ;
14- use super :: navigation:: { inner_creates_scope, is_star_or_plus_quantifier} ;
14+ use super :: navigation:: { inner_creates_scope, is_star_or_plus_quantifier, is_truly_empty_scope } ;
1515
1616/// Capture effects to attach to the innermost match instruction.
1717///
@@ -42,21 +42,29 @@ impl Compiler<'_> {
4242 let is_array = is_star_or_plus_quantifier ( inner) ;
4343
4444 // Check if inner is a scope-creating expression (SeqExpr/AltExpr) that produces
45- // a structured type (Struct/Enum). Named nodes with bubble captures don't count -
46- // they still need Node because we're capturing the matched node, not the struct.
45+ // a structured type (Struct/Enum) or truly empty struct. Named nodes with bubble
46+ // captures don't count - they still need Node because we're capturing the matched
47+ // node, not the struct.
4748 //
4849 // For FieldExpr, look through to the value. The parser treats `field: expr @cap` as
4950 // `(field: expr) @cap` so that quantifiers work on fields (e.g., `decorator: (x)*`
5051 // for repeating fields). This means captures wrap the FieldExpr, but the value
5152 // determines whether it produces a structured type. See `parse_expr_no_suffix`.
5253 let creates_structured_scope = inner. and_then ( unwrap_field_value) . is_some_and ( |ei| {
53- inner_creates_scope ( & ei)
54- && self
55- . type_ctx
56- . get_term_info ( & ei)
57- . and_then ( |info| info. flow . type_id ( ) )
58- . and_then ( |id| self . type_ctx . get_type ( id) )
59- . is_some_and ( |shape| matches ! ( shape, TypeShape :: Struct ( _) | TypeShape :: Enum ( _) ) )
54+ // Truly empty scopes (like `{ }`) produce empty struct
55+ if is_truly_empty_scope ( & ei) {
56+ return true ;
57+ }
58+ if !inner_creates_scope ( & ei) {
59+ return false ;
60+ }
61+ let Some ( info) = self . type_ctx . get_term_info ( & ei) else {
62+ return false ;
63+ } ;
64+ info. flow
65+ . type_id ( )
66+ . and_then ( |id| self . type_ctx . get_type ( id) )
67+ . is_some_and ( |shape| matches ! ( shape, TypeShape :: Struct ( _) | TypeShape :: Enum ( _) ) )
6068 } ) ;
6169
6270 if !is_structured_ref && !creates_structured_scope && !is_array {
0 commit comments