@@ -7640,8 +7640,22 @@ fn (mut c Checker) mark_as_referenced(mut node ast.Expr, as_interface bool) {
76407640 ast.Ident {
76417641 if mut node.obj is ast.Var {
76427642 mut obj := unsafe { & node.obj }
7643- if c.fn_scope != unsafe { nil } {
7644- obj = c.fn_scope.find_var (node.obj.name) or { obj }
7643+ // Resolve the canonical declaration variable so that the
7644+ // `is_auto_heap` promotion below is recorded on the variable
7645+ // that cgen will see when emitting its declaration. Walk the
7646+ // use-site scope chain (so variables declared in nested scopes,
7647+ // e.g. inside a `for` loop body, are found, unlike
7648+ // `c.fn_scope.find_var` which only locates function-level vars),
7649+ // while skipping synthetic smartcast vars from `if x is T`/`match`
7650+ // branches: those are copies with no declaration of their own, so
7651+ // promoting them would leave the real declaration emitted as a
7652+ // plain value and desync the pointer indirection.
7653+ obj = node.scope.find_var_decl (node.obj.name) or {
7654+ if c.fn_scope != unsafe { nil } {
7655+ c.fn_scope.find_var (node.obj.name) or { obj }
7656+ } else {
7657+ obj
7658+ }
76457659 }
76467660 if obj.typ == 0 {
76477661 return
@@ -7681,6 +7695,21 @@ fn (mut c Checker) mark_as_referenced(mut node ast.Expr, as_interface bool) {
76817695 }
76827696 }
76837697
7698+ if obj.is_auto_heap {
7699+ // `obj` is the canonical declaration, which cgen emits as a
7700+ // heap pointer. When the value is read through a branch-local
7701+ // smartcast/option-unwrap copy (`if x is T`, `if x != none`),
7702+ // cgen resolves that use-site copy (see
7703+ // `resolved_ident_is_auto_heap`) when emitting the read, so it
7704+ // must carry the same `is_auto_heap`. Otherwise the read (e.g.
7705+ // an unwrapped option's `.data`) is emitted without the pointer
7706+ // indirection the declaration was given, producing invalid C.
7707+ node.obj.is_auto_heap = true
7708+ if mut use_site := node.scope.find_var (node.obj.name) {
7709+ use_site.is_auto_heap = true
7710+ }
7711+ }
7712+
76847713 if as_interface {
76857714 for method in type_sym.methods {
76867715 c.mark_fn_decl_as_referenced (method.fkey ())
0 commit comments