From a23e06184d0dfd5546c568353a17563a9578d4c5 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 22 Oct 2022 15:53:27 +0300 Subject: [PATCH] checker: fix taking a closure of x, where `x` may be coming from a non trivial parent scope, like `for x in y {` or `x,y := multi()` (fix #16141) (#16147) --- vlib/v/checker/fn.v | 1 + vlib/v/tests/closure_test.v | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 53a67a1825..7a1288f4dd 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -428,6 +428,7 @@ fn (mut c Checker) anon_fn(mut node ast.AnonFn) ast.Type { if var.typ.has_flag(.generic) { has_generic = true } + node.decl.scope.update_var_type(var.name, var.typ) } c.stmts(node.decl.stmts) c.fn_decl(mut node.decl) diff --git a/vlib/v/tests/closure_test.v b/vlib/v/tests/closure_test.v index 299fca39dc..cdf6336b74 100644 --- a/vlib/v/tests/closure_test.v +++ b/vlib/v/tests/closure_test.v @@ -179,7 +179,7 @@ struct Command { struct App {} -fn main() { +fn test_larger_closure_parameters() { mut app := &App{} eprintln('app ptr: ${u64(app)}') f := fn [mut app] (cmd Command) u64 { @@ -198,3 +198,28 @@ fn main() { println('> res: $res | sizeof Command: ${sizeof(Command)}') assert res == u64(app) } + +fn test_closure_in_for_in_loop() { + a := [2, 4, 6, 9] + for v in a { + func := fn [v] (msg string) string { + return '$msg: $v' + } + res := func('hello') + assert res == 'hello: $v' + // dump(res) + } +} + +fn ret_two() (int, int) { + return 2, 5 +} + +fn test_closure_over_variable_that_is_returned_from_a_multi_value_function() { + one, two := ret_two() + a := fn [one] () { + println(one) + } + a() + println(two) +}