From 076fae5c900dc0b58dcfe65fab6479440b7c0909 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 15 Dec 2025 22:34:04 +0800 Subject: [PATCH] cgen,checker: fix array map anon fn return fixed array (fix #25928) (#25977) --- vlib/v/checker/fn.v | 12 +++++++++++- vlib/v/gen/c/array.v | 9 +++++++++ .../tests/array_map_anon_return_fixed_array_test.v | 13 +++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/array_map_anon_return_fixed_array_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index cc7c04ade..63cddd97b 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -3512,7 +3512,17 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as // map/filter are supposed to have 1 arg only mut arg_type := unaliased_left_type for mut arg in node.args { - arg_type = c.check_expr_option_or_result_call(arg.expr, c.expr(mut arg.expr)) + mut expr_type := c.expr(mut arg.expr) + if arg.expr is ast.AnonFn { + // fix anon fn when return is a fixed array + expr_sym := c.table.sym(expr_type) + info := expr_sym.info as ast.FnType + return_type_sym := c.table.sym(info.func.return_type) + if return_type_sym.kind == .array_fixed { + expr_type = c.cast_fixed_array_ret(info.func.return_type, return_type_sym) + } + } + arg_type = c.check_expr_option_or_result_call(arg.expr, expr_type) } if method_name == 'map' { // eprintln('>>>>>>> map node.args[0].expr: ${node.args[0].expr}, left_type: ${left_type} | elem_typ: ${elem_typ} | arg_type: ${arg_type}') diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 899cc07e8..b4862266e 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -525,6 +525,7 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { } else { (ret_sym.info as ast.ArrayFixed).elem_type } + ret_elem_sym := g.table.final_sym(ret_elem_type) mut ret_elem_styp := g.styp(ret_elem_type) inp_elem_type := if left_is_array { (inp_sym.info as ast.Array).elem_type @@ -576,12 +577,20 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { match mut expr { ast.AnonFn { g.write('${ret_elem_styp} ${tmp_map_expr_result_name} = ') + if ret_elem_sym.kind == .array_fixed { + // unpack fixed array return value + g.writeln('{0};') + g.write('memcpy(&${tmp_map_expr_result_name}, ') + } if expr.inherited_vars.len > 0 { g.write_closure_fn(mut expr, var_name, closure_var) } else { g.gen_anon_fn_decl(mut expr) g.write('${expr.decl.name}(${var_name})') } + if ret_elem_sym.kind == .array_fixed { + g.write('.ret_arr, sizeof(${ret_elem_styp}))') + } } ast.Ident { g.write('${ret_elem_styp} ${tmp_map_expr_result_name} = ') diff --git a/vlib/v/tests/array_map_anon_return_fixed_array_test.v b/vlib/v/tests/array_map_anon_return_fixed_array_test.v new file mode 100644 index 000000000..4328df74f --- /dev/null +++ b/vlib/v/tests/array_map_anon_return_fixed_array_test.v @@ -0,0 +1,13 @@ +module main + +fn test_array_map_anon_return_fixed_array() { + lines := ['1,2', '3,4', '5,7'] + coords := lines.map(fn (line string) [2]int { + xs, ys := line.split_once(',') or { panic('invalid input') } + x := xs.int() + y := ys.int() + return [x, y]! + }) + + assert coords == [[1, 2]!, [3, 4]!, [5, 7]!] +} -- 2.39.5