checker,cgen: implement alias operator overloading for generic struct parent type (fix #23965) (#23967)

This commit is contained in:
Swastik Baranwal 2025-03-18 12:53:48 +05:30 committed by GitHub
parent bd2ec679f0
commit 29e60da614
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 7 deletions

View File

@ -797,20 +797,28 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
if left_sym.kind == .struct && (left_sym.info as ast.Struct).generic_types.len > 0 { if left_sym.kind == .struct && (left_sym.info as ast.Struct).generic_types.len > 0 {
continue continue
} }
if method := left_sym.find_method(extracted_op) { if method := left_sym.find_method_with_generic_parent(extracted_op) {
if method.return_type != left_type_unwrapped { if method.return_type != left_type_unwrapped {
c.error('operator `${extracted_op}` must return `${left_name}` to be used as an assignment operator', c.error('operator `${extracted_op}` must return `${left_name}` to be used as an assignment operator',
node.pos) node.pos)
} }
} else { } else {
if !parent_sym.is_primitive() { if method := parent_sym.find_method_with_generic_parent(extracted_op) {
if left_name == right_name { if parent_sym.kind == .alias
c.error('undefined operation `${left_name}` ${extracted_op} `${right_name}`', && (parent_sym.info as ast.Alias).parent_type != method.return_type {
node.pos) c.error('operator `${extracted_op}` must return `${left_name}` to be used as an assignment operator',
} else {
c.error('mismatched types `${left_name}` and `${right_name}`',
node.pos) node.pos)
} }
} else {
if !parent_sym.is_primitive() {
if left_name == right_name {
c.error('undefined operation `${left_name}` ${extracted_op} `${right_name}`',
node.pos)
} else {
c.error('mismatched types `${left_name}` and `${right_name}`',
node.pos)
}
}
} }
} }
} }

View File

@ -674,6 +674,19 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
g.write(';') g.write(';')
} }
return return
} else if left_sym.kind == .alias && g.table.final_sym(var_type).kind == .struct {
struct_info := g.table.final_sym(var_type)
if struct_info.info is ast.Struct && struct_info.info.generic_types.len > 0 {
mut method_name := struct_info.cname + '_' + util.replace_op(extracted_op)
method_name = g.generic_fn_name(struct_info.info.concrete_types,
method_name)
g.write(' = ${method_name}(')
g.expr(left)
g.write(', ')
g.expr(val)
g.writeln(');')
return
}
} else { } else {
if g.table.final_sym(g.unwrap_generic(var_type)).kind == .array_fixed { if g.table.final_sym(g.unwrap_generic(var_type)).kind == .array_fixed {
g.go_back_to(pos) g.go_back_to(pos)

View File

@ -0,0 +1,18 @@
import math.vec
type V2 = vec.Vec2[f32]
fn test_alias_generic_parent_operator_overloading() {
a := V2{1, 1}
b := V2{10, 20}
mut c := a + b
assert c.x == 11.0
assert c.y == 21.0
dump(c)
c += a
assert c.x == 12.0
assert c.y == 22.0
dump(c)
}