1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: add checks for operator overloading (#7737)

This commit is contained in:
Swastik Baranwal 2020-12-31 17:08:10 +05:30 committed by GitHub
parent 5597925d58
commit a834f33661
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 0 deletions

View File

@ -4868,6 +4868,22 @@ 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.params.len != 2 {
c.error('operator methods should have exactly 1 argument', node.pos)
} else {
receiver_sym := c.table.get_type_symbol(node.receiver.typ)
param_sym := c.table.get_type_symbol(node.params[1].typ)
if param_sym.kind !in [.struct_, .alias] || receiver_sym.kind !in [.struct_, .alias] {
c.error('operator methods are only allowed for struct and type alias',
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)
}
}
}
}
// TODO c.pref.is_vet
if node.language == .v && !node.is_method && node.params.len == 0 && node.name.after('.').starts_with('test_') {
if !c.file.path.ends_with('_test.v') {

View File

@ -0,0 +1,20 @@
vlib/v/checker/tests/method_op_err.vv:11:1: error: operator methods should have exactly 1 argument
9 | }
10 |
11 | fn (u User) + () {
| ~~~~~~~~~~~~~~~~
12 | }
13 |
vlib/v/checker/tests/method_op_err.vv:14:1: error: both sides of an operator must be the same type
12 | }
13 |
14 | fn (u User) - (f Foo) User {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
15 | return User{u.a - f.a, u.b-f.a}
16 | }
vlib/v/checker/tests/method_op_err.vv:20:24: error: infix expr: cannot use `Foo` (right expression) as `User`
18 | fn main() {
19 | println(User{3, 4})
20 | println(User{3, 4} - Foo{3, 3})
| ^
21 | }

View File

@ -0,0 +1,21 @@
struct User {
a int
b int
}
struct Foo {
a int
b int
}
fn (u User) + () {
}
fn (u User) - (f Foo) User {
return User{u.a - f.a, u.b-f.a}
}
fn main() {
println(User{3, 4})
println(User{3, 4} - Foo{3, 3})
}