checker: improve message and positioning for operator overloading (#8133)
parent
ee9f9c9d81
commit
ef627c9d21
|
@ -792,7 +792,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
|||
left_name := c.table.type_to_str(left_type)
|
||||
right_name := c.table.type_to_str(right_type)
|
||||
if left_name == right_name {
|
||||
c.error('operation `$left_name` $infix_expr.op.str() `$right_name` does not exist, please define it',
|
||||
c.error('undefined operation `$left_name` $infix_expr.op.str() `$right_name`',
|
||||
left_pos)
|
||||
} else {
|
||||
c.error('mismatched types `$left_name` and `$right_name`', left_pos)
|
||||
|
@ -809,7 +809,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
|||
left_name := c.table.type_to_str(left_type)
|
||||
right_name := c.table.type_to_str(right_type)
|
||||
if left_name == right_name {
|
||||
c.error('operation `$left_name` $infix_expr.op.str() `$right_name` does not exist, please define it',
|
||||
c.error('undefined operation `$left_name` $infix_expr.op.str() `$right_name`',
|
||||
right_pos)
|
||||
} else {
|
||||
c.error('mismatched types `$left_name` and `$right_name`', right_pos)
|
||||
|
@ -852,7 +852,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
|||
left_name := c.table.type_to_str(left_type)
|
||||
right_name := c.table.type_to_str(right_type)
|
||||
if left_name == right_name {
|
||||
c.error('operation `$left_name` $infix_expr.op.str() `$right_name` does not exist, please define it',
|
||||
c.error('undefined operation `$left_name` $infix_expr.op.str() `$right_name`',
|
||||
infix_expr.pos)
|
||||
} else {
|
||||
c.error('mismatched types `$left_name` and `$right_name`', infix_expr.pos)
|
||||
|
@ -2600,7 +2600,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
|||
assign_stmt.pos)
|
||||
}
|
||||
if left_name == right_name {
|
||||
c.error('operation `$left_name` $extracted_op `$right_name` does not exist, please define it',
|
||||
c.error('undefined operation `$left_name` $extracted_op `$right_name`',
|
||||
assign_stmt.pos)
|
||||
} else {
|
||||
c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
|
||||
|
@ -5227,7 +5227,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
} 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)
|
||||
c.error('expected `$receiver_sym.name` not `$param_sym.name` - both operands must be the same type for operator overloading',
|
||||
node.params[1].type_pos)
|
||||
} else if node.name in ['<', '>', '==', '!=', '>=', '<='] &&
|
||||
node.return_type != table.bool_type
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
vlib/v/checker/tests/method_op_alias_err.vv:4:1: error: both sides of an operator must be the same type
|
||||
vlib/v/checker/tests/method_op_alias_err.vv:4:18: error: expected `Foo` not `Foo2` - both operands must be the same type for operator overloading
|
||||
2 | type Foo2 = string
|
||||
3 |
|
||||
4 | fn (f Foo) + (f1 Foo2) Foo2 {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| ~~~~
|
||||
5 | return Foo2(f + f1)
|
||||
6 | }
|
||||
vlib/v/checker/tests/method_op_alias_err.vv:5:19: error: infix expr: cannot use `string` (right expression) as `string`
|
||||
|
|
|
@ -5,11 +5,11 @@ vlib/v/checker/tests/method_op_err.vv:11:1: error: operator methods should have
|
|||
| ~~~~~~~~~~~~~~~~
|
||||
12 | }
|
||||
13 |
|
||||
vlib/v/checker/tests/method_op_err.vv:14:1: error: both sides of an operator must be the same type
|
||||
vlib/v/checker/tests/method_op_err.vv:14:18: error: expected `User` not `Foo` - both operands must be the same type for operator overloading
|
||||
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:18:1: error: operator comparison methods should return `bool`
|
||||
|
@ -40,7 +40,7 @@ vlib/v/checker/tests/method_op_err.vv:36:24: error: infix expr: cannot use `Foo`
|
|||
| ^
|
||||
37 | println(User{3, 2} < User{2, 4})
|
||||
38 | println(User{3, 4} < Foo{3, 4})
|
||||
vlib/v/checker/tests/method_op_err.vv:37:24: error: operation `User` < `User` does not exist, please define it
|
||||
vlib/v/checker/tests/method_op_err.vv:37:24: error: undefined operation `User` < `User`
|
||||
35 | println(User{3, 4})
|
||||
36 | println(User{3, 4} - Foo{3, 3})
|
||||
37 | println(User{3, 2} < User{2, 4})
|
||||
|
|
|
@ -609,6 +609,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
|||
}
|
||||
mut arg_pos := [p.tok.position()]
|
||||
mut arg_names := [p.check_name()]
|
||||
mut type_pos := [p.tok.position()]
|
||||
// `a, b, c int`
|
||||
for p.tok.kind == .comma {
|
||||
if !p.pref.is_fmt {
|
||||
|
@ -618,6 +619,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
|||
p.next()
|
||||
arg_pos << p.tok.position()
|
||||
arg_names << p.check_name()
|
||||
type_pos << p.tok.position()
|
||||
}
|
||||
if p.tok.kind == .key_mut {
|
||||
// TODO remove old syntax
|
||||
|
@ -665,6 +667,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
|||
name: arg_name
|
||||
is_mut: is_mut
|
||||
typ: typ
|
||||
type_pos: type_pos[i]
|
||||
}
|
||||
// if typ.typ.kind == .variadic && p.tok.kind == .comma {
|
||||
if is_variadic && p.tok.kind == .comma {
|
||||
|
|
|
@ -53,6 +53,7 @@ pub:
|
|||
name string
|
||||
is_mut bool
|
||||
typ Type
|
||||
type_pos token.Position
|
||||
is_hidden bool // interface first arg
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue