Skip to content

Commit 883eaa6

Browse files
authored
cgen: fix cross method call + method_call cleanup (#20025)
1 parent fed3552 commit 883eaa6

File tree

3 files changed

+55
-19
lines changed

3 files changed

+55
-19
lines changed

vlib/v/gen/c/assign.v

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,11 +1081,12 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
10811081
}
10821082
ast.CallExpr {
10831083
if val.is_method {
1084-
rec_cc_type := g.cc_type(val.receiver_type, false)
1085-
mut rec_typ_name := util.no_dots(rec_cc_type)
1086-
if g.table.sym(val.receiver_type).kind == .array {
1087-
rec_typ_name = 'array'
1088-
}
1084+
unwrapped_rec_type, typ_sym := g.resolve_receiver_type(val)
1085+
left_type := g.unwrap_generic(val.left_type)
1086+
left_sym := g.table.sym(left_type)
1087+
final_left_sym := g.table.final_sym(left_type)
1088+
rec_typ_name := g.resolve_receiver_name(val, unwrapped_rec_type, final_left_sym,
1089+
left_sym, typ_sym)
10891090
fn_name := util.no_dots('${rec_typ_name}_${val.name}')
10901091
g.write('${fn_name}(&')
10911092
g.gen_cross_tmp_variable(left, val.left)

vlib/v/gen/c/fn.v

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,14 +1158,22 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret
11581158
return comptime_args
11591159
}
11601160

1161-
fn (mut g Gen) method_call(node ast.CallExpr) {
1162-
// TODO: there are still due to unchecked exprs (opt/some fn arg)
1163-
if node.left_type == 0 {
1164-
g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos)
1161+
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 {
1162+
mut receiver_type_name := util.no_dots(g.cc_type(unwrapped_rec_type, false))
1163+
if final_left_sym.kind == .map && node.name in ['clone', 'move'] {
1164+
receiver_type_name = 'map'
11651165
}
1166-
if node.receiver_type == 0 {
1167-
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
1166+
if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name))
1167+
&& node.name in ['clear', 'repeat', 'sort_with_compare', 'sorted_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] {
1168+
if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) {
1169+
// `array_Xyz_clone` => `array_clone`
1170+
receiver_type_name = 'array'
1171+
}
11681172
}
1173+
return receiver_type_name
1174+
}
1175+
1176+
fn (mut g Gen) resolve_receiver_type(node ast.CallExpr) (ast.Type, &ast.TypeSymbol) {
11691177
left_type := g.unwrap_generic(node.left_type)
11701178
mut unwrapped_rec_type := node.receiver_type
11711179
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) {
12151223
unwrapped_rec_type = node.from_embed_types.last()
12161224
typ_sym = g.table.sym(unwrapped_rec_type)
12171225
}
1226+
return unwrapped_rec_type, typ_sym
1227+
}
1228+
1229+
fn (mut g Gen) method_call(node ast.CallExpr) {
1230+
// TODO: there are still due to unchecked exprs (opt/some fn arg)
1231+
if node.left_type == 0 {
1232+
g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos)
1233+
}
1234+
if node.receiver_type == 0 {
1235+
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
1236+
}
1237+
left_type := g.unwrap_generic(node.left_type)
1238+
mut unwrapped_rec_type, typ_sym := g.resolve_receiver_type(node)
1239+
12181240
rec_cc_type := g.cc_type(unwrapped_rec_type, false)
12191241
mut receiver_type_name := util.no_dots(rec_cc_type)
1220-
if mut typ_sym.info is ast.Interface && typ_sym.info.defines_method(node.name) {
1242+
if typ_sym.info is ast.Interface && typ_sym.info.defines_method(node.name) {
12211243
// Speaker_name_table[s._interface_idx].speak(s._object)
12221244
$if debug_interface_method_call ? {
12231245
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) {
13061328
g.get_free_method(rec_type)
13071329
}
13081330
mut has_cast := false
1309-
if final_left_sym.kind == .map && node.name in ['clone', 'move'] {
1310-
receiver_type_name = 'map'
1311-
}
1331+
1332+
receiver_type_name = g.resolve_receiver_name(node, unwrapped_rec_type, final_left_sym,
1333+
left_sym, typ_sym)
13121334
if final_left_sym.kind == .array && !(left_sym.kind == .alias && left_sym.has_method(node.name))
13131335
&& node.name in ['clear', 'repeat', 'sort_with_compare', 'sorted_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] {
1314-
if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) {
1315-
// `array_Xyz_clone` => `array_clone`
1316-
receiver_type_name = 'array'
1317-
}
13181336
if node.name in ['last', 'first', 'pop'] {
13191337
return_type_str := g.typ(node.return_type)
13201338
has_cast = true

vlib/v/tests/cross_method_call_test.v

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fn test_main() {
2+
mut l_map := map[int]bool{}
3+
mut r_map := map[int]bool{}
4+
5+
l_map[0] = false
6+
l_map[1] = false
7+
8+
r_map[0] = true
9+
r_map[1] = true
10+
11+
l_map, r_map = r_map.move(), l_map.move()
12+
13+
assert l_map[0] == true
14+
assert l_map[0] == true
15+
assert r_map[0] == false
16+
assert r_map[0] == false
17+
}

0 commit comments

Comments
 (0)