From 5a1699dec2da62aacdfd0b46b95ebe9af15e3633 Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Tue, 12 Jan 2021 09:07:20 +0530 Subject: [PATCH] checker: add more checks for operator overloading (#8030) --- vlib/v/checker/checker.v | 9 +++-- vlib/v/checker/tests/method_op_err.out | 48 +++++++++++++++++--------- vlib/v/checker/tests/method_op_err.vv | 8 +++++ 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b9730b81d8..dc0c024e73 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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 { diff --git a/vlib/v/checker/tests/method_op_err.out b/vlib/v/checker/tests/method_op_err.out index cbee61bf66..0c77048108 100644 --- a/vlib/v/checker/tests/method_op_err.out +++ b/vlib/v/checker/tests/method_op_err.out @@ -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 | } diff --git a/vlib/v/checker/tests/method_op_err.vv b/vlib/v/checker/tests/method_op_err.vv index e15fe4e624..a3cb8ff402 100644 --- a/vlib/v/checker/tests/method_op_err.vv +++ b/vlib/v/checker/tests/method_op_err.vv @@ -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})