From a100b0564726040ecbc8d2338f88994b9f8f9325 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 7 Dec 2020 17:37:17 +0000 Subject: [PATCH] checker: improve 'operator not defined on right operand type' error (#7185) --- vlib/v/checker/checker.v | 37 +++++++++---------- .../checker/tests/assign_expr_type_err_e.out | 2 +- .../checker/tests/assign_expr_type_err_f.out | 2 +- .../checker/tests/assign_expr_type_err_g.out | 2 +- .../checker/tests/assign_expr_type_err_h.out | 2 +- .../checker/tests/assign_expr_type_err_i.out | 2 +- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 25cabe6bfe..c7bcdaca96 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2218,28 +2218,27 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { // Single side check match assign_stmt.op { .assign {} // No need to do single side check for =. But here put it first for speed. - .plus_assign { - if !left_sym.is_number() && left_type != table.string_type && !left_sym.is_pointer() { - c.error('operator += not defined on left operand type `$left_sym.name`', - left.position()) - } else if !right_sym.is_number() && right_type != table.string_type && !right_sym.is_pointer() { - c.error('operator += not defined on right operand type `$right_sym.name`', - right.position()) - } - if right is ast.IntegerLiteral && right.str().int() == 1 { - c.error('use `++` instead of `+= 1`', assign_stmt.pos) - } - } - .minus_assign { - if !left_sym.is_number() && !left_sym.is_pointer() { - c.error('operator -= not defined on left operand type `$left_sym.name`', + .plus_assign, .minus_assign { + if left_type == table.string_type { + if assign_stmt.op != .plus_assign { + c.error('operator `$assign_stmt.op` not defined on left operand type `$left_sym.name`', + left.position()) + } + if right_type != table.string_type { + c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name', + right.position()) + } + } else if !left_sym.is_number() && !left_sym.is_pointer() { + c.error('operator `$assign_stmt.op` not defined on left operand type `$left_sym.name`', left.position()) } else if !right_sym.is_number() && !right_sym.is_pointer() { - c.error('operator -= not defined on right operand type `$right_sym.name`', + c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name', right.position()) - } - if right is ast.IntegerLiteral && right.str().int() == 1 { - c.error('use `--` instead of `-= 1`', assign_stmt.pos) + } else if right is ast.IntegerLiteral { + if right.val == '1' { + op := if assign_stmt.op == .plus_assign { token.Kind.inc } else { token.Kind.dec } + c.error('use `$op` instead of `$assign_stmt.op 1`', assign_stmt.pos) + } } } .mult_assign, .div_assign { diff --git a/vlib/v/checker/tests/assign_expr_type_err_e.out b/vlib/v/checker/tests/assign_expr_type_err_e.out index 943b11dafc..713316f762 100644 --- a/vlib/v/checker/tests/assign_expr_type_err_e.out +++ b/vlib/v/checker/tests/assign_expr_type_err_e.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/assign_expr_type_err_e.vv:3:2: error: operator -= not defined on left operand type `string` +vlib/v/checker/tests/assign_expr_type_err_e.vv:3:2: error: operator `-=` not defined on left operand type `string` 1 | fn main() { 2 | mut foo := 'hello' 3 | foo -= `a` diff --git a/vlib/v/checker/tests/assign_expr_type_err_f.out b/vlib/v/checker/tests/assign_expr_type_err_f.out index ac9b460bbd..180a100060 100644 --- a/vlib/v/checker/tests/assign_expr_type_err_f.out +++ b/vlib/v/checker/tests/assign_expr_type_err_f.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/assign_expr_type_err_f.vv:3:9: error: operator -= not defined on right operand type `bool` +vlib/v/checker/tests/assign_expr_type_err_f.vv:3:9: error: invalid right operand: int -= bool 1 | fn main() { 2 | mut foo := 10 3 | foo -= false diff --git a/vlib/v/checker/tests/assign_expr_type_err_g.out b/vlib/v/checker/tests/assign_expr_type_err_g.out index 95d8212ca2..75d6205065 100644 --- a/vlib/v/checker/tests/assign_expr_type_err_g.out +++ b/vlib/v/checker/tests/assign_expr_type_err_g.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/assign_expr_type_err_g.vv:3:2: error: operator += not defined on left operand type `bool` +vlib/v/checker/tests/assign_expr_type_err_g.vv:3:2: error: operator `+=` not defined on left operand type `bool` 1 | fn main() { 2 | mut foo := true 3 | foo += false diff --git a/vlib/v/checker/tests/assign_expr_type_err_h.out b/vlib/v/checker/tests/assign_expr_type_err_h.out index 0ee452f1ac..873f33b5f1 100644 --- a/vlib/v/checker/tests/assign_expr_type_err_h.out +++ b/vlib/v/checker/tests/assign_expr_type_err_h.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/assign_expr_type_err_h.vv:3:9: error: operator += not defined on right operand type `bool` +vlib/v/checker/tests/assign_expr_type_err_h.vv:3:9: error: invalid right operand: string += bool 1 | fn main() { 2 | mut foo := 'hello' 3 | foo += false diff --git a/vlib/v/checker/tests/assign_expr_type_err_i.out b/vlib/v/checker/tests/assign_expr_type_err_i.out index 1edbbc0719..3d14130464 100644 --- a/vlib/v/checker/tests/assign_expr_type_err_i.out +++ b/vlib/v/checker/tests/assign_expr_type_err_i.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/assign_expr_type_err_i.vv:3:9: error: cannot assign to `foo`: expected `f64`, not `string` +vlib/v/checker/tests/assign_expr_type_err_i.vv:3:9: error: invalid right operand: f64 += string 1 | fn main() { 2 | mut foo := 1.5 3 | foo += 'hello'