From bdc8586ddd8ef33a9a4f0f433576e996cd9b6504 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 15 Jun 2021 09:43:10 +0800 Subject: [PATCH] checker, cgen: fix `for in mut val` (#10444) --- vlib/v/checker/checker.v | 17 +++++++++++++++++ vlib/v/checker/tests/method_op_alias_err.out | 13 ++++++------- vlib/v/checker/tests/mismatched_ptr_op_ptr.out | 8 -------- vlib/v/checker/tests/sum_type_infix_err.out | 10 +++++----- vlib/v/checker/tests/sum_type_infix_err.vv | 4 ++-- vlib/v/gen/c/cgen.v | 7 ++++--- vlib/v/tests/for_in_mut_val_test.v | 12 ++++++++++++ 7 files changed, 46 insertions(+), 25 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f708ef7155..247edfcc49 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1156,6 +1156,23 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { c.error('mismatched types `$left_name` and `$right_name`', left_right_pos) } } + } else if (left_sym.kind == .string && !left_type.has_flag(.optional)) + || (right_sym.kind == .string && !right_type.has_flag(.optional)) { + deref_left_type := if node.left.is_auto_deref_var() { + left_type.deref() + } else { + left_type + } + deref_right_type := if node.right.is_auto_deref_var() { + right_type.deref() + } else { + right_type + } + left_name := c.table.type_to_str(deref_left_type) + right_name := c.table.type_to_str(deref_right_type) + if left_name != right_name { + c.error('mismatched types `$left_name` and `$right_name`', left_right_pos) + } } else { promoted_type := c.promote(c.table.unalias_num_type(left_type), c.table.unalias_num_type(right_type)) if promoted_type.idx() == ast.void_type_idx { diff --git a/vlib/v/checker/tests/method_op_alias_err.out b/vlib/v/checker/tests/method_op_alias_err.out index 27d4c4a4b5..1fab346331 100644 --- a/vlib/v/checker/tests/method_op_alias_err.out +++ b/vlib/v/checker/tests/method_op_alias_err.out @@ -1,12 +1,12 @@ 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 | + 3 | 4 | fn (f Foo) + (f1 Foo2) Foo2 { | ~~~~ 5 | return Foo2(f + f1) 6 | } -vlib/v/checker/tests/method_op_alias_err.vv:5:17: error: infix expr: cannot use `string` (right expression) as `string` - 3 | +vlib/v/checker/tests/method_op_alias_err.vv:5:17: error: mismatched types `Foo` and `Foo2` + 3 | 4 | fn (f Foo) + (f1 Foo2) Foo2 { 5 | return Foo2(f + f1) | ~~~~~~ @@ -14,7 +14,7 @@ vlib/v/checker/tests/method_op_alias_err.vv:5:17: error: infix expr: cannot use 7 | vlib/v/checker/tests/method_op_alias_err.vv:8:1: error: cannot define operator methods on type alias for `string` 6 | } - 7 | + 7 | 8 | fn (f Foo) * (f1 Foo) Foo { | ~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | return Foo(f + f1) @@ -31,13 +31,12 @@ vlib/v/checker/tests/method_op_alias_err.vv:15:9: error: cannot assign to `f`: e 14 | f += 'fg' 15 | f *= Foo2('2') | ~~~~~~~~~ - 16 | f -= Foo('fo') + 16 | f -= Foo('fo') 17 | println(f) vlib/v/checker/tests/method_op_alias_err.vv:16:6: error: cannot use operator methods on type alias for `string` 14 | f += 'fg' 15 | f *= Foo2('2') - 16 | f -= Foo('fo') + 16 | f -= Foo('fo') | ~~ 17 | println(f) 18 | } - diff --git a/vlib/v/checker/tests/mismatched_ptr_op_ptr.out b/vlib/v/checker/tests/mismatched_ptr_op_ptr.out index 0173927f7b..8ff6ee0e11 100644 --- a/vlib/v/checker/tests/mismatched_ptr_op_ptr.out +++ b/vlib/v/checker/tests/mismatched_ptr_op_ptr.out @@ -5,11 +5,3 @@ vlib/v/checker/tests/mismatched_ptr_op_ptr.vv:5:17: error: mismatched types `&st | ~~~ 6 | println(b+b) 7 | } -vlib/v/checker/tests/mismatched_ptr_op_ptr.vv:6:17: error: mismatched types `&string` and `&string` - 4 | b := &a - 5 | println(b+*b) - 6 | println(b+b) - | ~~~ - 7 | } - 8 | } - diff --git a/vlib/v/checker/tests/sum_type_infix_err.out b/vlib/v/checker/tests/sum_type_infix_err.out index e969913089..6a06f1b90c 100644 --- a/vlib/v/checker/tests/sum_type_infix_err.out +++ b/vlib/v/checker/tests/sum_type_infix_err.out @@ -3,12 +3,12 @@ vlib/v/checker/tests/sum_type_infix_err.vv:5:9: error: cannot use operator `+` w 4 | x := Abc(0) 5 | _ := x + Abc(5) | ^ - 6 | _ := 'test' + x + 6 | _ := 123 + x 7 | _ = unsafe{&x + 5} -vlib/v/checker/tests/sum_type_infix_err.vv:6:14: error: cannot use operator `+` with `Abc` +vlib/v/checker/tests/sum_type_infix_err.vv:6:11: error: cannot use operator `+` with `Abc` 4 | x := Abc(0) 5 | _ := x + Abc(5) - 6 | _ := 'test' + x - | ^ + 6 | _ := 123 + x + | ^ 7 | _ = unsafe{&x + 5} - 8 | } \ No newline at end of file + 8 | } diff --git a/vlib/v/checker/tests/sum_type_infix_err.vv b/vlib/v/checker/tests/sum_type_infix_err.vv index b4c40748f3..938dd6f831 100644 --- a/vlib/v/checker/tests/sum_type_infix_err.vv +++ b/vlib/v/checker/tests/sum_type_infix_err.vv @@ -3,6 +3,6 @@ type Abc = int | string fn main() { x := Abc(0) _ := x + Abc(5) - _ := 'test' + x + _ := 123 + x _ = unsafe{&x + 5} -} \ No newline at end of file +} diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 6b66904f44..828857139d 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3874,13 +3874,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { } else { (left_sym.info as ast.Alias).parent_type } - nr_muls := '*'.repeat(the_left_type.nr_muls()) + left_nr_muls := '*'.repeat(the_left_type.nr_muls()) g.write(g.typ(the_left_type.set_nr_muls(0))) g.write('_') g.write(util.replace_op(node.op.str())) - g.write('($nr_muls') + g.write('($left_nr_muls') g.expr(node.left) - g.write(', $nr_muls') + right_nr_muls := '*'.repeat(node.right_type.nr_muls()) + g.write(', $right_nr_muls') g.expr(node.right) g.write(')') } else if node.op in [.ne, .gt, .ge, .le] && ((is_v_struct && !is_alias && not_exception) diff --git a/vlib/v/tests/for_in_mut_val_test.v b/vlib/v/tests/for_in_mut_val_test.v index b89b317f48..19d071745f 100644 --- a/vlib/v/tests/for_in_mut_val_test.v +++ b/vlib/v/tests/for_in_mut_val_test.v @@ -83,3 +83,15 @@ fn test_for_in_mut_val_of_map_fixed_array() { println(m) assert '$m' == "{'foo': [{'c': 3}], 'bar': [{'c': 3}]}" } + +fn test_for_in_mut_val_of_plus_expr() { + b := 'c' + mut c := ['a', 'b'] + mut ret := []string{} + for mut a in c { + a = a + b + ret << a + } + println(ret) + assert ret == ['ac', 'bc'] +}