checker: add checks for operator overloading (#7737)
							parent
							
								
									5597925d58
								
							
						
					
					
						commit
						a834f33661
					
				|  | @ -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') { | ||||
|  |  | |||
|  | @ -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 | } | ||||
|  | @ -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}) | ||||
| } | ||||
		Loading…
	
		Reference in New Issue