diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index cb2833887a..60aecb9bc7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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 { diff --git a/vlib/v/checker/tests/method_op_alias_err.out b/vlib/v/checker/tests/method_op_alias_err.out index 1b800807d5..d6872025e3 100644 --- a/vlib/v/checker/tests/method_op_alias_err.out +++ b/vlib/v/checker/tests/method_op_alias_err.out @@ -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` diff --git a/vlib/v/checker/tests/method_op_err.out b/vlib/v/checker/tests/method_op_err.out index db1271b02b..e32d5e9913 100644 --- a/vlib/v/checker/tests/method_op_err.out +++ b/vlib/v/checker/tests/method_op_err.out @@ -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}) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index d5b41a119f..259df6e1f9 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -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 { diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index f1629495da..b0f6be3308 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -53,6 +53,7 @@ pub: name string is_mut bool typ Type + type_pos token.Position is_hidden bool // interface first arg }