From 02a47f42f3f7d242b32c655e391a71ffdf89b9ac Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 26 Aug 2022 18:37:10 +0800 Subject: [PATCH] ast, parser, cgen: fix closure with nested closure variable (#15542) --- vlib/v/ast/ast.v | 1 + vlib/v/gen/c/fn.v | 13 ++++++++++- vlib/v/parser/fn.v | 1 + .../inout/closure_with_nested_closure_var.out | 2 ++ .../inout/closure_with_nested_closure_var.vv | 23 +++++++++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/inout/closure_with_nested_closure_var.out create mode 100644 vlib/v/tests/inout/closure_with_nested_closure_var.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 08946d6a1..6784712b7 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -644,6 +644,7 @@ pub: is_arg bool // fn args should not be autofreed is_auto_deref bool is_inherited bool + has_inherited bool pub mut: expr Expr typ Type diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index ab8d4c39b..18b2aefb9 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -460,7 +460,18 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) { g.write('__closure_create($fn_name, ($ctx_struct*) memdup_uncollectable(&($ctx_struct){') g.indent++ for var in node.inherited_vars { - g.writeln('.$var.name = $var.name,') + mut has_inherited := false + if obj := node.decl.scope.find(var.name) { + if obj is ast.Var { + if obj.has_inherited { + has_inherited = true + g.writeln('.$var.name = $c.closure_ctx->$var.name,') + } + } + } + if !has_inherited { + g.writeln('.$var.name = $var.name,') + } } g.indent-- g.write('}, sizeof($ctx_struct)))') diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index f01696f6d..cc7fee499 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -1042,6 +1042,7 @@ fn (mut p Parser) closure_vars() []ast.Param { ...(*var) pos: var_pos is_inherited: true + has_inherited: var.is_inherited is_used: false is_changed: false is_mut: is_mut diff --git a/vlib/v/tests/inout/closure_with_nested_closure_var.out b/vlib/v/tests/inout/closure_with_nested_closure_var.out new file mode 100644 index 000000000..c3ba5a402 --- /dev/null +++ b/vlib/v/tests/inout/closure_with_nested_closure_var.out @@ -0,0 +1,2 @@ +Test1{}, Test(Test1{}) +Test1{}, Test(Test1{}) diff --git a/vlib/v/tests/inout/closure_with_nested_closure_var.vv b/vlib/v/tests/inout/closure_with_nested_closure_var.vv new file mode 100644 index 000000000..7ac1abe2d --- /dev/null +++ b/vlib/v/tests/inout/closure_with_nested_closure_var.vv @@ -0,0 +1,23 @@ +module main + +interface Test { + test(fn (Test)) +} + +struct Test1 { +} + +fn (t Test1) test(f fn (Test)) { + f(Test(t)) +} + +fn main() { + t := Test1{} + + t.test(fn [t] (t1 Test) { + println('$t, $t1') + t.test(fn [t] (t2 Test) { + println('$t, $t2') + }) + }) +} -- 2.30.2