1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix missing check for unwrapped shift operation (#18451)

This commit is contained in:
Felipe Pena 2023-06-16 03:49:24 -03:00 committed by GitHub
parent 84cf448f2f
commit d17f6f69cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 54 additions and 24 deletions

View File

@ -457,7 +457,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
} else if node.left !in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector]
&& (left_type.has_flag(.option) || right_type.has_flag(.option)) {
opt_comp_pos := if left_type.has_flag(.option) { left_pos } else { right_pos }
c.error('unwrapped option cannot be compared in an infix expression',
c.error('unwrapped Option cannot be compared in an infix expression',
opt_comp_pos)
}
}
@ -471,6 +471,11 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
if !node.is_stmt {
c.error('array append cannot be used in an expression', node.pos)
}
if left_type.has_flag(.option) && node.left is ast.Ident
&& (node.left as ast.Ident).or_expr.kind == .absent {
c.error('unwrapped Option cannot be used in an infix expression',
node.pos)
}
// `array << elm`
c.check_expr_opt_call(node.right, right_type)
node.auto_locked, _ = c.fail_if_immutable(node.left)
@ -695,7 +700,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
opt_infix_pos := if left_is_option { left_pos } else { right_pos }
if (node.left !in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector]
|| node.op in [.eq, .ne, .lt, .gt, .le, .ge]) && right_sym.kind != .none_ {
c.error('unwrapped option cannot be used in an infix expression', opt_infix_pos)
c.error('unwrapped Option cannot be used in an infix expression', opt_infix_pos)
}
}
@ -703,7 +708,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
right_is_result := right_type.has_flag(.result)
if left_is_result || right_is_result {
opt_infix_pos := if left_is_result { left_pos } else { right_pos }
c.error('unwrapped result cannot be used in an infix expression', opt_infix_pos)
c.error('unwrapped Result cannot be used in an infix expression', opt_infix_pos)
}
// Dual sides check (compatibility check)

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/infix_compare_option_err.vv:6:5: error: unwrapped option cannot be compared in an infix expression
4 |
vlib/v/checker/tests/infix_compare_option_err.vv:6:5: error: unwrapped Option cannot be compared in an infix expression
4 |
5 | fn main() {
6 | if foo() > foo() {
| ~~~~~
7 | }
8 | }
8 | }

View File

@ -17,17 +17,17 @@ vlib/v/checker/tests/infix_err.vv:9:9: error: `+` cannot be used with `?string`
8 | _ = f() + ''
9 | _ = f() + f()
| ^
10 |
10 |
11 | _ = 4 + g()
vlib/v/checker/tests/infix_err.vv:11:7: error: `+` cannot be used with `?int`
9 | _ = f() + f()
10 |
10 |
11 | _ = 4 + g()
| ^
12 | _ = int(0) + g() // FIXME not detected
13 | _ = g() + int(3)
vlib/v/checker/tests/infix_err.vv:12:14: error: unwrapped option cannot be used in an infix expression
10 |
vlib/v/checker/tests/infix_err.vv:12:14: error: unwrapped Option cannot be used in an infix expression
10 |
11 | _ = 4 + g()
12 | _ = int(0) + g() // FIXME not detected
| ~~~
@ -45,10 +45,10 @@ vlib/v/checker/tests/infix_err.vv:14:9: error: `+` cannot be used with `?int`
13 | _ = g() + int(3)
14 | _ = g() + 3
| ^
15 |
15 |
16 | // binary operands
vlib/v/checker/tests/infix_err.vv:17:5: error: left operand for `&&` is not a boolean
15 |
15 |
16 | // binary operands
17 | _ = 1 && 2
| ^
@ -59,10 +59,10 @@ vlib/v/checker/tests/infix_err.vv:18:13: error: right operand for `||` is not a
17 | _ = 1 && 2
18 | _ = true || 2
| ^
19 |
19 |
20 | // boolean expressions
vlib/v/checker/tests/infix_err.vv:21:22: error: ambiguous boolean expression. use `()` to ensure correct order of operations
19 |
19 |
20 | // boolean expressions
21 | _ = 1 == 1 && 2 == 2 || 3 == 3
| ~~
@ -78,4 +78,4 @@ vlib/v/checker/tests/infix_err.vv:24:2: error: ambiguous boolean expression. use
22 | _ = 1 == 1
23 | && 2 == 2 || 3 == 3
24 | && 4 == 4
| ~~
| ~~

View File

@ -1,25 +1,25 @@
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:3:10: error: unwrapped option cannot be used in an infix expression
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:3:10: error: unwrapped Option cannot be used in an infix expression
1 | fn main() {
2 | a := ?string("hi")
3 | println(a == 'hi')
| ^
4 | println('hi' == a)
5 | println(a != 'hi')
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:4:18: error: unwrapped option cannot be used in an infix expression
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:4:18: error: unwrapped Option cannot be used in an infix expression
2 | a := ?string("hi")
3 | println(a == 'hi')
4 | println('hi' == a)
| ^
5 | println(a != 'hi')
6 | println('hi' != a)
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:5:10: error: unwrapped option cannot be used in an infix expression
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:5:10: error: unwrapped Option cannot be used in an infix expression
3 | println(a == 'hi')
4 | println('hi' == a)
5 | println(a != 'hi')
| ^
6 | println('hi' != a)
7 | }
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:6:18: error: unwrapped option cannot be used in an infix expression
vlib/v/checker/tests/option_wrapped_cmp_op_err.vv:6:18: error: unwrapped Option cannot be used in an infix expression
4 | println('hi' == a)
5 | println(a != 'hi')
6 | println('hi' != a)

View File

@ -1,5 +1,5 @@
vlib/v/checker/tests/unwrapped_option_infix.vv:5:9: error: unwrapped option cannot be used in an infix expression
vlib/v/checker/tests/unwrapped_option_infix.vv:5:9: error: unwrapped Option cannot be used in an infix expression
3 | }
4 |
4 |
5 | println(test() == '')
| ~~~~~~
| ~~~~~~

View File

@ -1,8 +1,7 @@
vlib/v/checker/tests/unwrapped_result_infix_err.vv:7:9: error: unwrapped result cannot be used in an infix expression
vlib/v/checker/tests/unwrapped_result_infix_err.vv:7:9: error: unwrapped Result cannot be used in an infix expression
5 | fn g() ! {
6 | assert f('1')! == true
7 | assert f('1') == true
| ~~~~~~
8 | }
9 |

View File

@ -0,0 +1,14 @@
vlib/v/checker/tests/wrong_shift_left_option_err.vv:7:4: error: unwrapped Option cannot be used in an infix expression
5 | fn main() {
6 | mut a := ?[]SomeStruct([SomeStruct{}, SomeStruct{}]) // struct type
7 | a << []SomeStruct{len: 20}
| ~~
8 | mut b := ?[]int([2, 8]) // primitive type
9 | b << [1, 3, 4]
vlib/v/checker/tests/wrong_shift_left_option_err.vv:9:4: error: unwrapped Option cannot be used in an infix expression
7 | a << []SomeStruct{len: 20}
8 | mut b := ?[]int([2, 8]) // primitive type
9 | b << [1, 3, 4]
| ~~
10 | dump(a?.len)
11 | dump(b)

View File

@ -0,0 +1,12 @@
pub struct SomeStruct {
i int
}
fn main() {
mut a := ?[]SomeStruct([SomeStruct{}, SomeStruct{}]) // struct type
a << []SomeStruct{len: 20}
mut b := ?[]int([2, 8]) // primitive type
b << [1, 3, 4]
dump(a?.len)
dump(b)
}