From 537605a058f5041d751765123aad6d9404b87516 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 25 Feb 2025 11:42:23 -0300 Subject: [PATCH] checker: fix map when casting to interface (fix #23790) (#23799) --- vlib/v/gen/c/array.v | 40 +++++++++++++++---- .../array_map_cast_interface_test.v | 34 ++++++++++++++++ 2 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/builtin_arrays/array_map_cast_interface_test.v diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index 710306695..35997fada 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -560,7 +560,9 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ var_name := g.get_array_expr_param_name(mut expr) - g.write_prepared_var(var_name, inp_elem_type, inp_elem_styp, past.tmp_var, i, left_is_array) + is_auto_heap := expr is ast.CastExpr && (expr.expr is ast.Ident && expr.expr.is_auto_heap()) + g.write_prepared_var(var_name, inp_elem_type, inp_elem_styp, past.tmp_var, i, left_is_array, + is_auto_heap) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -976,7 +978,8 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) { i := g.new_tmp_var() g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, info.elem_type, elem_type_str, past.tmp_var, i, true) + g.write_prepared_var(var_name, info.elem_type, elem_type_str, past.tmp_var, i, true, + false) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -1477,7 +1480,8 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array) + g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array, + false) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -1567,7 +1571,8 @@ fn (mut g Gen) gen_array_count(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array) + g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array, + false) g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false match mut expr { @@ -1659,7 +1664,8 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) { g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {') g.indent++ - g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array) + g.write_prepared_var(var_name, elem_type, elem_type_str, past.tmp_var, i, left_is_array, + false) g.empty_line = true g.set_current_pos_as_last_stmt_pos() mut is_embed_map_filter := false @@ -1770,7 +1776,7 @@ fn (mut g Gen) write_prepared_tmp_value(tmp string, node &ast.CallExpr, tmp_styp } fn (mut g Gen) write_prepared_var(var_name string, elem_type ast.Type, inp_elem_type string, tmp string, - i string, is_array bool) { + i string, is_array bool, auto_heap bool) { elem_sym := g.table.sym(elem_type) if is_array { if elem_sym.kind == .array_fixed { @@ -1779,16 +1785,34 @@ fn (mut g Gen) write_prepared_var(var_name string, elem_type ast.Type, inp_elem_ } else if elem_sym.kind == .function { g.writeln('voidptr ${var_name} = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];') } else { - g.writeln('${inp_elem_type} ${var_name} = ((${inp_elem_type}*) ${tmp}_orig.data)[${i}];') + g.write('${inp_elem_type} ') + if auto_heap { + g.write('*') + } + g.write('${var_name} = ') + if auto_heap { + g.write('&') + } + g.writeln('((${inp_elem_type}*) ${tmp}_orig.data)[${i}];') } } else { if elem_sym.kind == .array_fixed { g.writeln('${inp_elem_type} ${var_name};') g.writeln('memcpy(&${var_name}, &${tmp}_orig[${i}], sizeof(${inp_elem_type}));') + } else if auto_heap { + g.writeln('${inp_elem_type} *${var_name} = &${tmp}_orig[${i}];') } else if elem_sym.kind == .function { g.writeln('voidptr ${var_name} = (voidptr)${tmp}_orig[${i}];') } else { - g.writeln('${inp_elem_type} ${var_name} = ${tmp}_orig[${i}];') + g.write('${inp_elem_type} ') + if auto_heap { + g.write('*') + } + g.write('${var_name} = ') + if auto_heap { + g.write('&') + } + g.writeln('${tmp}_orig[${i}];') } } } diff --git a/vlib/v/tests/builtin_arrays/array_map_cast_interface_test.v b/vlib/v/tests/builtin_arrays/array_map_cast_interface_test.v new file mode 100644 index 000000000..58798f19b --- /dev/null +++ b/vlib/v/tests/builtin_arrays/array_map_cast_interface_test.v @@ -0,0 +1,34 @@ +interface Rect { + width u32 + height u32 +} + +struct Square { + side u32 + width u32 + height u32 +} + +fn test_main() { + squares := [Square{ + side: 5 + width: 5 + height: 5 + }] + rects := squares.map(Rect(it)) + + assert rects.str() == '[Rect(Square{ + side: 5 + width: 5 + height: 5 +})]' +} + +fn test_fixed_array() { + squares := [Square{ + side: 5 + width: 5 + height: 5 + }]! + rects := squares.map(Rect(it)) +} -- 2.39.5