diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 277e26bda6..162b0da770 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -1081,11 +1081,12 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) { } ast.CallExpr { if val.is_method { - rec_cc_type := g.cc_type(val.receiver_type, false) - mut rec_typ_name := util.no_dots(rec_cc_type) - if g.table.sym(val.receiver_type).kind == .array { - rec_typ_name = 'array' - } + unwrapped_rec_type, typ_sym := g.resolve_receiver_type(val) + left_type := g.unwrap_generic(val.left_type) + left_sym := g.table.sym(left_type) + final_left_sym := g.table.final_sym(left_type) + rec_typ_name := g.resolve_receiver_name(val, unwrapped_rec_type, final_left_sym, + left_sym, typ_sym) fn_name := util.no_dots('${rec_typ_name}_${val.name}') g.write('${fn_name}(&') g.gen_cross_tmp_variable(left, val.left) diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 7bdc0308a5..d599c67afa 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1158,14 +1158,22 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret return comptime_args } -fn (mut g Gen) method_call(node ast.CallExpr) { - // TODO: there are still due to unchecked exprs (opt/some fn arg) - if node.left_type == 0 { - g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos) +fn (mut g Gen) resolve_receiver_name(node ast.CallExpr, unwrapped_rec_type ast.Type, final_left_sym ast.TypeSymbol, left_sym ast.TypeSymbol, typ_sym ast.TypeSymbol) string { + mut receiver_type_name := util.no_dots(g.cc_type(unwrapped_rec_type, false)) + if final_left_sym.kind == .map && node.name in ['clone', 'move'] { + receiver_type_name = 'map' } - if node.receiver_type == 0 { - g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos) + if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name)) + && node.name in ['clear', 'repeat', 'sort_with_compare', 'sorted_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] { + if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) { + // `array_Xyz_clone` => `array_clone` + receiver_type_name = 'array' + } } + return receiver_type_name +} + +fn (mut g Gen) resolve_receiver_type(node ast.CallExpr) (ast.Type, &ast.TypeSymbol) { left_type := g.unwrap_generic(node.left_type) mut unwrapped_rec_type := node.receiver_type if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 { // in generic fn @@ -1215,9 +1223,23 @@ fn (mut g Gen) method_call(node ast.CallExpr) { unwrapped_rec_type = node.from_embed_types.last() typ_sym = g.table.sym(unwrapped_rec_type) } + return unwrapped_rec_type, typ_sym +} + +fn (mut g Gen) method_call(node ast.CallExpr) { + // TODO: there are still due to unchecked exprs (opt/some fn arg) + if node.left_type == 0 { + g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos) + } + if node.receiver_type == 0 { + g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos) + } + left_type := g.unwrap_generic(node.left_type) + mut unwrapped_rec_type, typ_sym := g.resolve_receiver_type(node) + rec_cc_type := g.cc_type(unwrapped_rec_type, false) mut receiver_type_name := util.no_dots(rec_cc_type) - if mut typ_sym.info is ast.Interface && typ_sym.info.defines_method(node.name) { + if typ_sym.info is ast.Interface && typ_sym.info.defines_method(node.name) { // Speaker_name_table[s._interface_idx].speak(s._object) $if debug_interface_method_call ? { eprintln('>>> interface typ_sym.name: ${typ_sym.name} | receiver_type_name: ${receiver_type_name} | pos: ${node.pos}') @@ -1306,15 +1328,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.get_free_method(rec_type) } mut has_cast := false - if final_left_sym.kind == .map && node.name in ['clone', 'move'] { - receiver_type_name = 'map' - } + + receiver_type_name = g.resolve_receiver_name(node, unwrapped_rec_type, final_left_sym, + left_sym, typ_sym) if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name)) && node.name in ['clear', 'repeat', 'sort_with_compare', 'sorted_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] { - if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) { - // `array_Xyz_clone` => `array_clone` - receiver_type_name = 'array' - } if node.name in ['last', 'first', 'pop'] { return_type_str := g.typ(node.return_type) has_cast = true diff --git a/vlib/v/tests/cross_method_call_test.v b/vlib/v/tests/cross_method_call_test.v new file mode 100644 index 0000000000..90e7e29560 --- /dev/null +++ b/vlib/v/tests/cross_method_call_test.v @@ -0,0 +1,17 @@ +fn test_main() { + mut l_map := map[int]bool{} + mut r_map := map[int]bool{} + + l_map[0] = false + l_map[1] = false + + r_map[0] = true + r_map[1] = true + + l_map, r_map = r_map.move(), l_map.move() + + assert l_map[0] == true + assert l_map[0] == true + assert r_map[0] == false + assert r_map[0] == false +}