From e92024f159a15444ad75485b6c3c74fa54cabfef Mon Sep 17 00:00:00 2001 From: yuyi98 Date: Sun, 20 Mar 2022 08:28:54 +0800 Subject: [PATCH] ast, checker, cgen: fix error for go anon fn variable call --- vlib/v/ast/ast.v | 2 ++ vlib/v/checker/fn.v | 4 ++++ vlib/v/gen/c/cgen.v | 2 ++ vlib/v/tests/go_anon_fn_variable_call_test.v | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+) create mode 100644 vlib/v/tests/go_anon_fn_variable_call_test.v diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 1673220ec3..8f0a1103c4 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -557,6 +557,7 @@ pub mut: name string // left.name() is_method bool is_field bool // temp hack, remove ASAP when re-impl CallExpr / Selector (joe) + is_fn_var bool // fn variable is_keep_alive bool // GC must not free arguments before fn returns is_noreturn bool // whether the function/method is marked as [noreturn] is_ctor_new bool // if JS ctor calls requires `new` before call, marked as `[use_new]` in V @@ -568,6 +569,7 @@ pub mut: left_type Type // type of `user` receiver_type Type // User return_type Type + fn_var_type Type // fn variable type should_be_skipped bool // true for calls to `[if someflag?]` functions, when there is no `-d someflag` concrete_types []Type // concrete types, e.g. concrete_list_pos token.Pos diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 590546b2f6..61e3f00096 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -600,9 +600,13 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) match obj { ast.GlobalField { typ = obj.typ + node.is_fn_var = true + node.fn_var_type = typ } ast.Var { typ = if obj.smartcasts.len != 0 { obj.smartcasts.last() } else { obj.typ } + node.is_fn_var = true + node.fn_var_type = typ } else {} } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 0c6b879a10..f40d88bc92 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5106,6 +5106,8 @@ fn (mut g Gen) go_expr(node ast.GoExpr) { } else if mut expr.left is ast.AnonFn { g.gen_anon_fn_decl(mut expr.left) name = expr.left.decl.name + } else if expr.is_fn_var { + name = g.table.sym(expr.fn_var_type).name } name = util.no_dots(name) if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') { diff --git a/vlib/v/tests/go_anon_fn_variable_call_test.v b/vlib/v/tests/go_anon_fn_variable_call_test.v new file mode 100644 index 0000000000..137091840b --- /dev/null +++ b/vlib/v/tests/go_anon_fn_variable_call_test.v @@ -0,0 +1,18 @@ +fn sum(a int, b int) int { + // Simply proxy the function into an anonymous function for demo purposes + sum_func := fn (a int, b int) int { + return a + b + } + + // and run it concurrently + g := go sum_func(a, b) + + result := g.wait() + return result +} + +fn test_go_anon_fn_variable_call() { + ret := sum(22, 33) + println(ret) + assert ret == 55 +}