Skip to content

Commit 29e60da

Browse files
authored
checker,cgen: implement alias operator overloading for generic struct parent type (fix #23965) (#23967)
1 parent bd2ec67 commit 29e60da

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

vlib/v/checker/assign.v

+15-7
Original file line numberDiff line numberDiff line change
@@ -797,20 +797,28 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
797797
if left_sym.kind == .struct && (left_sym.info as ast.Struct).generic_types.len > 0 {
798798
continue
799799
}
800-
if method := left_sym.find_method(extracted_op) {
800+
if method := left_sym.find_method_with_generic_parent(extracted_op) {
801801
if method.return_type != left_type_unwrapped {
802802
c.error('operator `${extracted_op}` must return `${left_name}` to be used as an assignment operator',
803803
node.pos)
804804
}
805805
} else {
806-
if !parent_sym.is_primitive() {
807-
if left_name == right_name {
808-
c.error('undefined operation `${left_name}` ${extracted_op} `${right_name}`',
809-
node.pos)
810-
} else {
811-
c.error('mismatched types `${left_name}` and `${right_name}`',
806+
if method := parent_sym.find_method_with_generic_parent(extracted_op) {
807+
if parent_sym.kind == .alias
808+
&& (parent_sym.info as ast.Alias).parent_type != method.return_type {
809+
c.error('operator `${extracted_op}` must return `${left_name}` to be used as an assignment operator',
812810
node.pos)
813811
}
812+
} else {
813+
if !parent_sym.is_primitive() {
814+
if left_name == right_name {
815+
c.error('undefined operation `${left_name}` ${extracted_op} `${right_name}`',
816+
node.pos)
817+
} else {
818+
c.error('mismatched types `${left_name}` and `${right_name}`',
819+
node.pos)
820+
}
821+
}
814822
}
815823
}
816824
}

vlib/v/gen/c/assign.v

+13
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,19 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
674674
g.write(';')
675675
}
676676
return
677+
} else if left_sym.kind == .alias && g.table.final_sym(var_type).kind == .struct {
678+
struct_info := g.table.final_sym(var_type)
679+
if struct_info.info is ast.Struct && struct_info.info.generic_types.len > 0 {
680+
mut method_name := struct_info.cname + '_' + util.replace_op(extracted_op)
681+
method_name = g.generic_fn_name(struct_info.info.concrete_types,
682+
method_name)
683+
g.write(' = ${method_name}(')
684+
g.expr(left)
685+
g.write(', ')
686+
g.expr(val)
687+
g.writeln(');')
688+
return
689+
}
677690
} else {
678691
if g.table.final_sym(g.unwrap_generic(var_type)).kind == .array_fixed {
679692
g.go_back_to(pos)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import math.vec
2+
3+
type V2 = vec.Vec2[f32]
4+
5+
fn test_alias_generic_parent_operator_overloading() {
6+
a := V2{1, 1}
7+
b := V2{10, 20}
8+
9+
mut c := a + b
10+
assert c.x == 11.0
11+
assert c.y == 21.0
12+
dump(c)
13+
14+
c += a
15+
assert c.x == 12.0
16+
assert c.y == 22.0
17+
dump(c)
18+
}

0 commit comments

Comments
 (0)