diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 8817dc5e32..d774f37a00 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2674,22 +2674,33 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) } // check for arg (var) of fn type if !found { - if v := node.scope.find_var(fn_name) { - if v.typ != 0 { - generic_vts := c.table.get_type_symbol(v.typ) - if generic_vts.kind == .function { - info := generic_vts.info as ast.FnType + mut typ := 0 + if obj := node.scope.find(node.name) { + match obj { + ast.GlobalField { + typ = obj.typ + } + ast.Var { + typ = if obj.smartcasts.len != 0 { obj.smartcasts.last() } else { obj.typ } + } + else {} + } + } + + if typ != 0 { + generic_vts := c.table.get_final_type_symbol(typ) + if generic_vts.kind == .function { + info := generic_vts.info as ast.FnType + func = info.func + found = true + found_in_args = true + } else { + vts := c.table.get_type_symbol(c.unwrap_generic(typ)) + if vts.kind == .function { + info := vts.info as ast.FnType func = info.func found = true found_in_args = true - } else { - vts := c.table.get_type_symbol(c.unwrap_generic(v.typ)) - if vts.kind == .function { - info := vts.info as ast.FnType - func = info.func - found = true - found_in_args = true - } } } } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index b6c476dcd1..d56729036a 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1180,7 +1180,41 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { // g.writeln(';') // g.write(cur_line + ' /* <== af cur line*/') // } - g.write(g.get_ternary_name(name)) + mut is_fn_var := false + if obj := node.scope.find(node.name) { + match obj { + ast.Var { + if obj.smartcasts.len > 0 { + for _ in obj.smartcasts { + g.write('(*') + } + for i, typ in obj.smartcasts { + cast_sym := g.table.get_type_symbol(g.unwrap_generic(typ)) + mut is_ptr := false + if i == 0 { + g.write(node.name) + if obj.orig_type.is_ptr() { + is_ptr = true + } + } + dot := if is_ptr { '->' } else { '.' } + if mut cast_sym.info is ast.Aggregate { + sym := g.table.get_type_symbol(cast_sym.info.types[g.aggregate_type_idx]) + g.write('${dot}_$sym.cname') + } else { + g.write('${dot}_$cast_sym.cname') + } + g.write(')') + } + is_fn_var = true + } + } + else {} + } + } + if !is_fn_var { + g.write(g.get_ternary_name(name)) + } if is_interface_call { g.write(')') } diff --git a/vlib/v/tests/fn_type_call_of_match_expr_test.v b/vlib/v/tests/fn_type_call_of_match_expr_test.v new file mode 100644 index 0000000000..c61ddbe42d --- /dev/null +++ b/vlib/v/tests/fn_type_call_of_match_expr_test.v @@ -0,0 +1,29 @@ +type FnZ = fn () string + +type FnO = fn (int) string + +type FnQ = FnO | FnZ + +fn fnz_z() string { + return 'Got zero' +} + +fn fnz_o(one int) string { + return 'Got one $one' +} + +fn test_fn_type_call_of_match_expr() { + mut arr := [FnQ(FnZ(fnz_z)), FnQ(FnO(fnz_o))] + for item in arr { + match item { + FnZ { + println(item()) + assert item() == 'Got zero' + } + FnO { + println(item(42)) + assert item(42) == 'Got one 42' + } + } + } +}