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:
parent
84cf448f2f
commit
d17f6f69cd
@ -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]
|
} else if node.left !in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector]
|
||||||
&& (left_type.has_flag(.option) || right_type.has_flag(.option)) {
|
&& (left_type.has_flag(.option) || right_type.has_flag(.option)) {
|
||||||
opt_comp_pos := if left_type.has_flag(.option) { left_pos } else { right_pos }
|
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)
|
opt_comp_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,6 +471,11 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||||||
if !node.is_stmt {
|
if !node.is_stmt {
|
||||||
c.error('array append cannot be used in an expression', node.pos)
|
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`
|
// `array << elm`
|
||||||
c.check_expr_opt_call(node.right, right_type)
|
c.check_expr_opt_call(node.right, right_type)
|
||||||
node.auto_locked, _ = c.fail_if_immutable(node.left)
|
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 }
|
opt_infix_pos := if left_is_option { left_pos } else { right_pos }
|
||||||
if (node.left !in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector]
|
if (node.left !in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector]
|
||||||
|| node.op in [.eq, .ne, .lt, .gt, .le, .ge]) && right_sym.kind != .none_ {
|
|| 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)
|
right_is_result := right_type.has_flag(.result)
|
||||||
if left_is_result || right_is_result {
|
if left_is_result || right_is_result {
|
||||||
opt_infix_pos := if left_is_result { left_pos } else { right_pos }
|
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)
|
// Dual sides check (compatibility check)
|
||||||
|
@ -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
|
vlib/v/checker/tests/infix_compare_option_err.vv:6:5: error: unwrapped Option cannot be compared in an infix expression
|
||||||
4 |
|
4 |
|
||||||
5 | fn main() {
|
5 | fn main() {
|
||||||
6 | if foo() > foo() {
|
6 | if foo() > foo() {
|
||||||
| ~~~~~
|
| ~~~~~
|
||||||
7 | }
|
7 | }
|
||||||
8 | }
|
8 | }
|
||||||
|
@ -17,17 +17,17 @@ vlib/v/checker/tests/infix_err.vv:9:9: error: `+` cannot be used with `?string`
|
|||||||
8 | _ = f() + ''
|
8 | _ = f() + ''
|
||||||
9 | _ = f() + f()
|
9 | _ = f() + f()
|
||||||
| ^
|
| ^
|
||||||
10 |
|
10 |
|
||||||
11 | _ = 4 + g()
|
11 | _ = 4 + g()
|
||||||
vlib/v/checker/tests/infix_err.vv:11:7: error: `+` cannot be used with `?int`
|
vlib/v/checker/tests/infix_err.vv:11:7: error: `+` cannot be used with `?int`
|
||||||
9 | _ = f() + f()
|
9 | _ = f() + f()
|
||||||
10 |
|
10 |
|
||||||
11 | _ = 4 + g()
|
11 | _ = 4 + g()
|
||||||
| ^
|
| ^
|
||||||
12 | _ = int(0) + g() // FIXME not detected
|
12 | _ = int(0) + g() // FIXME not detected
|
||||||
13 | _ = g() + int(3)
|
13 | _ = g() + int(3)
|
||||||
vlib/v/checker/tests/infix_err.vv:12:14: error: unwrapped option cannot be used in an infix expression
|
vlib/v/checker/tests/infix_err.vv:12:14: error: unwrapped Option cannot be used in an infix expression
|
||||||
10 |
|
10 |
|
||||||
11 | _ = 4 + g()
|
11 | _ = 4 + g()
|
||||||
12 | _ = int(0) + g() // FIXME not detected
|
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)
|
13 | _ = g() + int(3)
|
||||||
14 | _ = g() + 3
|
14 | _ = g() + 3
|
||||||
| ^
|
| ^
|
||||||
15 |
|
15 |
|
||||||
16 | // binary operands
|
16 | // binary operands
|
||||||
vlib/v/checker/tests/infix_err.vv:17:5: error: left operand for `&&` is not a boolean
|
vlib/v/checker/tests/infix_err.vv:17:5: error: left operand for `&&` is not a boolean
|
||||||
15 |
|
15 |
|
||||||
16 | // binary operands
|
16 | // binary operands
|
||||||
17 | _ = 1 && 2
|
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
|
17 | _ = 1 && 2
|
||||||
18 | _ = true || 2
|
18 | _ = true || 2
|
||||||
| ^
|
| ^
|
||||||
19 |
|
19 |
|
||||||
20 | // boolean expressions
|
20 | // boolean expressions
|
||||||
vlib/v/checker/tests/infix_err.vv:21:22: error: ambiguous boolean expression. use `()` to ensure correct order of operations
|
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
|
20 | // boolean expressions
|
||||||
21 | _ = 1 == 1 && 2 == 2 || 3 == 3
|
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
|
22 | _ = 1 == 1
|
||||||
23 | && 2 == 2 || 3 == 3
|
23 | && 2 == 2 || 3 == 3
|
||||||
24 | && 4 == 4
|
24 | && 4 == 4
|
||||||
| ~~
|
| ~~
|
||||||
|
@ -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() {
|
1 | fn main() {
|
||||||
2 | a := ?string("hi")
|
2 | a := ?string("hi")
|
||||||
3 | println(a == 'hi')
|
3 | println(a == 'hi')
|
||||||
| ^
|
| ^
|
||||||
4 | println('hi' == a)
|
4 | println('hi' == a)
|
||||||
5 | println(a != 'hi')
|
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")
|
2 | a := ?string("hi")
|
||||||
3 | println(a == 'hi')
|
3 | println(a == 'hi')
|
||||||
4 | println('hi' == a)
|
4 | println('hi' == a)
|
||||||
| ^
|
| ^
|
||||||
5 | println(a != 'hi')
|
5 | println(a != 'hi')
|
||||||
6 | println('hi' != a)
|
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')
|
3 | println(a == 'hi')
|
||||||
4 | println('hi' == a)
|
4 | println('hi' == a)
|
||||||
5 | println(a != 'hi')
|
5 | println(a != 'hi')
|
||||||
| ^
|
| ^
|
||||||
6 | println('hi' != a)
|
6 | println('hi' != a)
|
||||||
7 | }
|
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)
|
4 | println('hi' == a)
|
||||||
5 | println(a != 'hi')
|
5 | println(a != 'hi')
|
||||||
6 | println('hi' != a)
|
6 | println('hi' != a)
|
||||||
|
@ -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 | }
|
3 | }
|
||||||
4 |
|
4 |
|
||||||
5 | println(test() == '')
|
5 | println(test() == '')
|
||||||
| ~~~~~~
|
| ~~~~~~
|
||||||
|
@ -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() ! {
|
5 | fn g() ! {
|
||||||
6 | assert f('1')! == true
|
6 | assert f('1')! == true
|
||||||
7 | assert f('1') == true
|
7 | assert f('1') == true
|
||||||
| ~~~~~~
|
| ~~~~~~
|
||||||
8 | }
|
8 | }
|
||||||
9 |
|
9 |
|
||||||
|
|
||||||
|
14
vlib/v/checker/tests/wrong_shift_left_option_err.out
Normal file
14
vlib/v/checker/tests/wrong_shift_left_option_err.out
Normal 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)
|
12
vlib/v/checker/tests/wrong_shift_left_option_err.vv
Normal file
12
vlib/v/checker/tests/wrong_shift_left_option_err.vv
Normal 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)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user