From 6fdcc5bcd07a3c49ec87cd5fdd9df65930847733 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 15 Aug 2022 11:52:08 +0800 Subject: [PATCH] checker, cgen: fix closure with fn variables (fix #15286) (#15427) --- vlib/v/checker/fn.v | 10 ++++++++- vlib/v/gen/c/fn.v | 22 +++++++++++++++++-- .../tests/inout/closure_with_fn_variables.out | 2 ++ .../tests/inout/closure_with_fn_variables.vv | 19 ++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/inout/closure_with_fn_variables.out create mode 100644 vlib/v/tests/inout/closure_with_fn_variables.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index fa0d28f96d..1968907ed4 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -674,7 +674,15 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) node.fn_var_type = typ } ast.Var { - typ = if obj.smartcasts.len != 0 { obj.smartcasts.last() } else { obj.typ } + if obj.smartcasts.len != 0 { + typ = obj.smartcasts.last() + } else { + if obj.typ == 0 { + typ = c.expr(obj.expr) + } else { + typ = obj.typ + } + } node.is_fn_var = true node.fn_var_type = typ } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 628b7ed23b..7b595e614a 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -473,8 +473,23 @@ fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) { ctx_struct := closure_ctx(node.decl) builder.writeln('$ctx_struct {') for var in node.inherited_vars { - styp := g.typ(var.typ) - builder.writeln('\t$styp $var.name;') + var_sym := g.table.sym(var.typ) + if var_sym.info is ast.FnType { + ret_styp := g.typ(var_sym.info.func.return_type) + builder.write_string('\t$ret_styp (*$var.name) (') + arg_len := var_sym.info.func.params.len + for j, arg in var_sym.info.func.params { + arg_styp := g.typ(arg.typ) + builder.write_string('$arg_styp $arg.name') + if j < arg_len - 1 { + builder.write_string(', ') + } + } + builder.writeln(');') + } else { + styp := g.typ(var.typ) + builder.writeln('\t$styp $var.name;') + } } builder.writeln('};\n') } @@ -1322,6 +1337,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { g.write(')') } is_fn_var = true + } else if obj.is_inherited { + g.write(c.closure_ctx + '->' + node.name) + is_fn_var = true } } else {} diff --git a/vlib/v/tests/inout/closure_with_fn_variables.out b/vlib/v/tests/inout/closure_with_fn_variables.out new file mode 100644 index 0000000000..bae42c55f9 --- /dev/null +++ b/vlib/v/tests/inout/closure_with_fn_variables.out @@ -0,0 +1,2 @@ +test1 +test2 diff --git a/vlib/v/tests/inout/closure_with_fn_variables.vv b/vlib/v/tests/inout/closure_with_fn_variables.vv new file mode 100644 index 0000000000..1d3a635795 --- /dev/null +++ b/vlib/v/tests/inout/closure_with_fn_variables.vv @@ -0,0 +1,19 @@ +module main + +fn test1() { + println('test1') +} + +fn test2() { + println('test2') +} + +fn main() { + t1 := test1 + t2 := test2 + anon := fn [t1, t2] () { + t1() + t2() + } + anon() +}