cgen: allow `==` to be user defined if `!=` is auto generated and vice versa (#8286)

pull/8298/head
Swastik Baranwal 2021-01-23 21:29:39 +05:30 committed by GitHub
parent 39e5f6e9df
commit 8a59ffb4b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 7 deletions

View File

@ -3171,13 +3171,42 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
}
g.expr(node.right)
g.write(')')
} else if node.op in [.eq, .ne] && left_sym.kind == .struct_ && right_sym.kind == .struct_
&& has_eq_overloaded&& has_ne_overloaded {
ptr_typ := g.gen_struct_equality_fn(left_type)
if node.op == .eq {
g.write('${ptr_typ}_struct_eq(')
} else if node.op == .ne {
g.write('!${ptr_typ}_struct_eq(')
} else if node.op in [.eq, .ne] && left_sym.kind == .struct_ && right_sym.kind == .struct_ {
if has_eq_overloaded && !has_ne_overloaded {
// Define `!=` as negation of Autogenerated `==`
styp := g.typ(left_type)
if node.op == .eq {
g.write('!${styp}__ne(')
} else if node.op == .ne {
g.write('${styp}__ne(')
}
}
if !has_eq_overloaded && has_ne_overloaded {
// Define `==` as negation of Autogenerated `!=`
styp := g.typ(left_type)
if node.op == .ne {
g.write('!${styp}__eq(')
} else if node.op == .eq {
g.write('${styp}__eq(')
}
}
if !has_eq_overloaded && !has_ne_overloaded {
// Overload both User defined `==` and `!=`
styp := g.typ(left_type)
if node.op == .eq {
g.write('${styp}__eq(')
} else if node.op == .ne {
g.write('${styp}__ne(')
}
}
if has_eq_overloaded && has_ne_overloaded {
// Auto generate both `==` and `!=`
ptr_typ := g.gen_struct_equality_fn(left_type)
if node.op == .eq {
g.write('${ptr_typ}_struct_eq(')
} else if node.op == .ne {
g.write('!${ptr_typ}_struct_eq(')
}
}
if node.left_type.is_ptr() {
g.write('*')

View File

@ -0,0 +1,15 @@
struct User {
name string
num int
}
fn (u User) == (u1 User) bool {
return u.name == u1.name
}
fn test_eq_op() {
u1 := User{'Joe', 23}
u2 := User{'Joe', 24}
assert u1 == u2
assert (u1 != u2) == false
}

View File

@ -0,0 +1,15 @@
struct User {
name string
num int
}
fn (u User) != (u1 User) bool {
return u.num != u1.num
}
fn test_eq_op() {
u1 := User{'Joe', 23}
u2 := User{'Joe', 24}
assert u1 != u2
assert (u1 == u2) == false
}