From a6f1667bce55f515cfaca53778d410790e198407 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 29 Nov 2020 00:34:26 +0200 Subject: [PATCH] checker: make `sym == typ` an error --- vlib/v/checker/checker.v | 32 +++++++++++-------- ...ypesymbol_to_a_type_should_not_compile.out | 7 ++++ vlib/v/gen/cgen.v | 2 +- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index aa633b1bdd..9142767b24 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -642,6 +642,14 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { // TODO: Some of the checks are not single side. Should find a better way to organize them. match infix_expr.op { // .eq, .ne, .gt, .lt, .ge, .le, .and, .logical_or, .dot, .key_as, .right_shift {} + .eq, .ne { + is_alias_eq_struct := left.kind == .alias && right.kind == .struct_ + is_struct_eq_alias := left.kind == .struct_ && right.kind == .alias + if is_alias_eq_struct || is_struct_eq_alias { + c.error('possible type mismatch of compared values of `$infix_expr.op` operation', + infix_expr.pos) + } + } .key_in, .not_in { match right.kind { .array { @@ -837,26 +845,22 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { } return table.void_type } - else { - if infix_expr.op in [.and, .logical_or] { - if infix_expr.left_type != table.bool_type_idx { - c.error('left operand for `$infix_expr.op` is not a boolean', infix_expr.left.position()) - } - if infix_expr.right_type != table.bool_type_idx { - c.error('right operand for `$infix_expr.op` is not a boolean', infix_expr.right.position()) - } + .and, .logical_or { + if infix_expr.left_type != table.bool_type_idx { + c.error('left operand for `$infix_expr.op` is not a boolean', infix_expr.left.position()) + } + if infix_expr.right_type != table.bool_type_idx { + c.error('right operand for `$infix_expr.op` is not a boolean', infix_expr.right.position()) } // use `()` to make the boolean expression clear error // for example: `(a && b) || c` instead of `a && b || c` - if infix_expr.op in [.logical_or, .and] { - if mut infix_expr.left is ast.InfixExpr { - if infix_expr.left.op in [.logical_or, .and] && - infix_expr.left.op != infix_expr.op { - c.error('use `()` to make the boolean expression clear', infix_expr.pos) - } + if mut infix_expr.left is ast.InfixExpr { + if infix_expr.left.op != infix_expr.op && infix_expr.left.op in [.logical_or, .and] { + c.error('use `()` to make the boolean expression clear', infix_expr.pos) } } } + else {} } // TODO: Absorb this block into the above single side check block to accelerate. if left_type == table.bool_type && infix_expr.op !in [.eq, .ne, .logical_or, .and] { diff --git a/vlib/v/checker/comparing_typesymbol_to_a_type_should_not_compile.out b/vlib/v/checker/comparing_typesymbol_to_a_type_should_not_compile.out index e69de29bb2..5a40312727 100644 --- a/vlib/v/checker/comparing_typesymbol_to_a_type_should_not_compile.out +++ b/vlib/v/checker/comparing_typesymbol_to_a_type_should_not_compile.out @@ -0,0 +1,7 @@ +vlib/v/checker/comparing_typesymbol_to_a_type_should_not_compile.vv:12:12: error: possible type mismatch of compared values of `==` operation + 10 | x := ityp == table.string_type + 11 | // the next line should produce at least a warning, or even an error, without an explicit cast: + 12 | z := isym == table.string_type + | ~~ + 13 | println(typeof(isym)) + 14 | println(typeof(table.string_type)) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 7cd9aba694..efde24cf2e 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1616,7 +1616,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { if left.left_type.is_ptr() { g.write('*') } - needs_clone := elem_typ == table.string_type && g.pref.autofree + needs_clone := info.elem_type == table.string_type && g.pref.autofree if needs_clone { g.write('/*1*/string_clone(') }