checker: add more checks for operator overloading (#8030)

pull/8056/head
Swastik Baranwal 2021-01-12 09:07:20 +05:30 committed by GitHub
parent 1559e72d0d
commit 5a1699dec2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 19 deletions

View File

@ -5114,7 +5114,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
c.error('.str() methods should have 0 arguments', node.pos)
}
}
if node.language == .v && node.is_method && node.name in ['+', '-', '*', '%', '/', '<', '>', '==', '!='] {
if node.language == .v && node.is_method && node.name in
['+', '-', '*', '%', '/', '<', '>', '==', '!=', '>=', '<='] {
if node.params.len != 2 {
c.error('operator methods should have exactly 1 argument', node.pos)
} else {
@ -5124,7 +5125,11 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
c.error('operator methods are only allowed for struct and type alias',
node.pos)
} else {
if node.receiver.typ != node.params[1].typ {
if node.rec_mut {
c.error('receiver cannot be `mut` for operator overloading', node.receiver_pos)
} else if node.params[1].is_mut {
c.error('argument cannot be `mut` for operator overloading', node.pos)
} else if node.receiver.typ != node.params[1].typ {
c.error('both sides of an operator must be the same type', node.pos)
} else if node.name in ['<', '>', '==', '!=', '>=', '<='] &&
node.return_type != table.bool_type {

View File

@ -19,23 +19,37 @@ vlib/v/checker/tests/method_op_err.vv:18:1: error: operator comparison methods s
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 | return User{}
20 | }
vlib/v/checker/tests/method_op_err.vv:24:24: error: infix expr: cannot use `Foo` (right expression) as `User`
22 | fn main() {
23 | println(User{3, 4})
24 | println(User{3, 4} - Foo{3, 3})
vlib/v/checker/tests/method_op_err.vv:22:9: error: receiver cannot be `mut` for operator overloading
20 | }
21 |
22 | fn (mut u User) * (u1 User) User {
| ~~~~~~
23 | return User{}
24 | }
vlib/v/checker/tests/method_op_err.vv:26:1: error: argument cannot be `mut` for operator overloading
24 | }
25 |
26 | fn (u User) / (mut u1 User) User {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 | return User{}
28 | }
vlib/v/checker/tests/method_op_err.vv:32:24: error: infix expr: cannot use `Foo` (right expression) as `User`
30 | fn main() {
31 | println(User{3, 4})
32 | println(User{3, 4} - Foo{3, 3})
| ^
25 | println(User{3, 2} < User{2, 4})
26 | println(User{3, 4} < Foo{3, 4})
vlib/v/checker/tests/method_op_err.vv:25:24: error: operation `User` < `User` does not exist, please define it
23 | println(User{3, 4})
24 | println(User{3, 4} - Foo{3, 3})
25 | println(User{3, 2} < User{2, 4})
33 | println(User{3, 2} < User{2, 4})
34 | println(User{3, 4} < Foo{3, 4})
vlib/v/checker/tests/method_op_err.vv:33:24: error: operation `User` < `User` does not exist, please define it
31 | println(User{3, 4})
32 | println(User{3, 4} - Foo{3, 3})
33 | println(User{3, 2} < User{2, 4})
| ^
26 | println(User{3, 4} < Foo{3, 4})
27 | }
vlib/v/checker/tests/method_op_err.vv:26:24: error: mismatched types `User` and `Foo`
24 | println(User{3, 4} - Foo{3, 3})
25 | println(User{3, 2} < User{2, 4})
26 | println(User{3, 4} < Foo{3, 4})
34 | println(User{3, 4} < Foo{3, 4})
35 | }
vlib/v/checker/tests/method_op_err.vv:34:24: error: mismatched types `User` and `Foo`
32 | println(User{3, 4} - Foo{3, 3})
33 | println(User{3, 2} < User{2, 4})
34 | println(User{3, 4} < Foo{3, 4})
| ^
27 | }
35 | }

View File

@ -19,6 +19,14 @@ fn (u User) > (u1 User) User {
return User{}
}
fn (mut u User) * (u1 User) User {
return User{}
}
fn (u User) / (mut u1 User) User {
return User{}
}
fn main() {
println(User{3, 4})
println(User{3, 4} - Foo{3, 3})