diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 4667040cb49be6..f6bb48835ac345 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -910,7 +910,7 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ } } else { g.expr(lx) - sym := g.table.sym(node.left_types[i]) + sym := g.table.final_sym(node.left_types[i]) if sym.kind == .array_fixed { g.writeln(';') g.writeln('memcpy(&${g.expr_string(lx)}, &${mr_var_name}.arg${i}, sizeof(${styp}));') diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index d08152c5a5d758..6721e506ffc4a9 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5504,6 +5504,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { || g.cur_lock.lockeds.len > 0 || (fn_return_is_multi && node.exprs.len >= 1 && fn_return_is_option) || fn_return_is_fixed_array + || (fn_return_is_multi && node.types.any(g.table.final_sym(it).kind == .array_fixed)) // handle promoting none/error/function returning _option' if fn_return_is_option { option_none := node.exprs[0] is ast.None @@ -5603,6 +5604,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { } // Use this to keep the tmp assignments in order mut multi_unpack := '' + mut final_assignments := '' g.write('(${styp}){') mut arg_idx := 0 for i, expr in node.exprs { @@ -5639,17 +5641,27 @@ fn (mut g Gen) return_stmt(node ast.Return) { continue } g.write('.arg${arg_idx}=') - if expr.is_auto_deref_var() { - g.write('*') - } - if mr_info.types[i].has_flag(.option) { - g.expr_with_opt(expr, node.types[i], mr_info.types[i]) - } else if g.table.sym(mr_info.types[i]).kind in [.sum_type, .interface_] { - g.expr_with_cast(expr, node.types[i], mr_info.types[i]) - } else { + if expr !is ast.ArrayInit && g.table.final_sym(node.types[i]).kind == .array_fixed { + line := g.go_before_last_stmt().trim_space() + expr_styp := g.typ(node.types[i]) + g.write('memcpy(&${tmpvar}.arg${arg_idx}, ') g.expr(expr) + g.writeln(', sizeof(${expr_styp}));') + final_assignments += g.go_before_last_stmt() + '\t' + g.write(line) + g.write('{0}') + } else { + if expr.is_auto_deref_var() { + g.write('*') + } + if mr_info.types[i].has_flag(.option) { + g.expr_with_opt(expr, node.types[i], mr_info.types[i]) + } else if g.table.sym(mr_info.types[i]).kind in [.sum_type, .interface_] { + g.expr_with_cast(expr, node.types[i], mr_info.types[i]) + } else { + g.expr(expr) + } } - if i < node.exprs.len - 1 { g.write(', ') } @@ -5669,6 +5681,10 @@ fn (mut g Gen) return_stmt(node ast.Return) { if multi_unpack != '' { g.insert_before_stmt(multi_unpack) } + if final_assignments != '' { + g.writeln(';') + g.write(final_assignments) + } if use_tmp_var && !fn_return_is_option && !fn_return_is_result { if !has_semicolon { g.writeln(';') diff --git a/vlib/v/tests/fns/multi_return_array_fixed_test.v b/vlib/v/tests/fns/multi_return_array_fixed_test.v new file mode 100644 index 00000000000000..f58162953af5d7 --- /dev/null +++ b/vlib/v/tests/fns/multi_return_array_fixed_test.v @@ -0,0 +1,19 @@ +module main + +type Mat4 = [2]f32 + +struct GameObject { +mut: + rot Mat4 = Mat4([f32(1.1), 2.2]!) + transform Mat4 = Mat4([f32(1.1), 2.2]!) +} + +fn (g GameObject) calc() (Mat4, Mat4) { + return g.rot, g.transform +} + +fn test_main() { + x, y := GameObject{}.calc() + assert x == Mat4([f32(1.1), 2.2]!) + assert y == Mat4([f32(1.1), 2.2]!) +}