Skip to content

Commit 02a47f4

Browse files
authored
ast, parser, cgen: fix closure with nested closure variable (#15542)
1 parent 3af1227 commit 02a47f4

File tree

5 files changed

+39
-1
lines changed

5 files changed

+39
-1
lines changed

vlib/v/ast/ast.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ pub:
644644
is_arg bool // fn args should not be autofreed
645645
is_auto_deref bool
646646
is_inherited bool
647+
has_inherited bool
647648
pub mut:
648649
expr Expr
649650
typ Type

vlib/v/gen/c/fn.v

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,18 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
460460
g.write('__closure_create($fn_name, ($ctx_struct*) memdup_uncollectable(&($ctx_struct){')
461461
g.indent++
462462
for var in node.inherited_vars {
463-
g.writeln('.$var.name = $var.name,')
463+
mut has_inherited := false
464+
if obj := node.decl.scope.find(var.name) {
465+
if obj is ast.Var {
466+
if obj.has_inherited {
467+
has_inherited = true
468+
g.writeln('.$var.name = $c.closure_ctx->$var.name,')
469+
}
470+
}
471+
}
472+
if !has_inherited {
473+
g.writeln('.$var.name = $var.name,')
474+
}
464475
}
465476
g.indent--
466477
g.write('}, sizeof($ctx_struct)))')

vlib/v/parser/fn.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ fn (mut p Parser) closure_vars() []ast.Param {
10421042
...(*var)
10431043
pos: var_pos
10441044
is_inherited: true
1045+
has_inherited: var.is_inherited
10451046
is_used: false
10461047
is_changed: false
10471048
is_mut: is_mut
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Test1{}, Test(Test1{})
2+
Test1{}, Test(Test1{})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module main
2+
3+
interface Test {
4+
test(fn (Test))
5+
}
6+
7+
struct Test1 {
8+
}
9+
10+
fn (t Test1) test(f fn (Test)) {
11+
f(Test(t))
12+
}
13+
14+
fn main() {
15+
t := Test1{}
16+
17+
t.test(fn [t] (t1 Test) {
18+
println('$t, $t1')
19+
t.test(fn [t] (t2 Test) {
20+
println('$t, $t2')
21+
})
22+
})
23+
}

0 commit comments

Comments
 (0)