diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index e487461295..95100b2280 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -182,6 +182,9 @@ pub fn (c &Checker) promote(left_type, right_type table.Type) table.Type { } if right_type.is_number() && left_type.is_number() { return c.promote_num(left_type, right_type) + } else if left_type.has_flag(.optional) != right_type.has_flag(.optional) { + // incompatible + return table.void_type } else { return left_type // default to left if not automatic promotion possible } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d111c085cb..b9cb4c5121 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -629,6 +629,9 @@ 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) c.error('mismatched types `$left_name` and `$right_name`', infix_expr.pos) + } else if promoted_type.has_flag(.optional) { + s := c.table.type_to_str(promoted_type) + c.error('`$infix_expr.op` cannot be used with `$s`', infix_expr.pos) } else if promoted_type.is_float() { if infix_expr.op in [.mod, .xor, .amp, .pipe] { side := if left_type == promoted_type { 'left' } else { 'right' } diff --git a/vlib/v/checker/tests/infix_err.out b/vlib/v/checker/tests/infix_err.out new file mode 100644 index 0000000000..ad27777325 --- /dev/null +++ b/vlib/v/checker/tests/infix_err.out @@ -0,0 +1,39 @@ +vlib/v/checker/tests/infix_err.vv:7:8: error: mismatched types `string` and `?string` + 5 | return none + 6 | } + 7 | _ = '' + f() + | ^ + 8 | _ = f() + '' + 9 | _ = f() + f() +vlib/v/checker/tests/infix_err.vv:8:9: error: mismatched types `?string` and `string` + 6 | } + 7 | _ = '' + f() + 8 | _ = f() + '' + | ^ + 9 | _ = f() + f() + 10 | +vlib/v/checker/tests/infix_err.vv:9:9: error: `+` cannot be used with `?string` + 7 | _ = '' + f() + 8 | _ = f() + '' + 9 | _ = f() + f() + | ^ + 10 | + 11 | _ = 4 + g() +vlib/v/checker/tests/infix_err.vv:11:7: error: `+` cannot be used with `?int` + 9 | _ = f() + f() + 10 | + 11 | _ = 4 + g() + | ^ + 12 | _ = int(0) + g() // FIXME not detected + 13 | _ = g() + int(3) +vlib/v/checker/tests/infix_err.vv:13:9: error: `+` cannot be used with `?int` + 11 | _ = 4 + g() + 12 | _ = int(0) + g() // FIXME not detected + 13 | _ = g() + int(3) + | ^ + 14 | _ = g() + 3 +vlib/v/checker/tests/infix_err.vv:14:9: error: `+` cannot be used with `?int` + 12 | _ = int(0) + g() // FIXME not detected + 13 | _ = g() + int(3) + 14 | _ = g() + 3 + | ^ diff --git a/vlib/v/checker/tests/infix_err.vv b/vlib/v/checker/tests/infix_err.vv new file mode 100644 index 0000000000..728a288f95 --- /dev/null +++ b/vlib/v/checker/tests/infix_err.vv @@ -0,0 +1,14 @@ +fn f() ?string { + return none +} +fn g() ?int { + return none +} +_ = '' + f() +_ = f() + '' +_ = f() + f() + +_ = 4 + g() +_ = int(0) + g() // FIXME not detected +_ = g() + int(3) +_ = g() + 3