Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

checker: add infix checks for nil #22045

Merged
merged 12 commits into from
Aug 18, 2024
34 changes: 34 additions & 0 deletions vlib/v/checker/infix.v
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,37 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
}
}
}

Delta456 marked this conversation as resolved.
Show resolved Hide resolved
// Do not allow comparing nil to non-pointers
if node.left.is_nil() {
mut final_type := right_type
if mut right_sym.info is ast.Alias
&& right_sym.info.parent_type.is_any_kind_of_pointer() {
final_type = right_sym.info.parent_type
}
if !final_type.is_any_kind_of_pointer() && (right_final_sym.kind != .function
|| (right_final_sym.language != .c && right_final_sym.kind == .placeholder))
&& !right_final_sym.is_heap() {
rt := c.table.sym(right_type).name
c.error('cannot compare with `nil` because `${rt}` is not a pointer',
node.pos)
}
}

if node.right.is_nil() {
mut final_type := left_type
if mut left_sym.info is ast.Alias
&& left_sym.info.parent_type.is_any_kind_of_pointer() {
final_type = left_sym.info.parent_type
}
if !final_type.is_any_kind_of_pointer() && (left_final_sym.kind != .function
|| (left_final_sym.language != .c && left_final_sym.kind == .placeholder))
&& !left_final_sym.is_heap() {
lt := c.table.sym(left_type).name
c.error('cannot compare with `nil` because `${lt}` is not a pointer',
node.pos)
}
}
}
.key_in, .not_in {
match right_final_sym.kind {
Expand Down Expand Up @@ -542,6 +573,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
c.error('unwrapped Option cannot be compared in an infix expression',
opt_comp_pos)
}
if node.left.is_nil() || node.right.is_nil() {
c.error('cannot use `${node.op.str()}` with `nil`', node.pos)
}
}
.key_like {
node.promoted_type = ast.bool_type
Expand Down
14 changes: 14 additions & 0 deletions vlib/v/checker/tests/nil_compare_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
vlib/v/checker/tests/nil_compare_err.vv:3:6: error: cannot compare with `nil` because `[]int` is not a pointer
1 | a := [12, 34, 56]
2 |
3 | if a != unsafe { nil } {
| ~~
4 | println(a)
5 | }
vlib/v/checker/tests/nil_compare_err.vv:7:7: error: cannot use `>` with `nil`
5 | }
6 |
7 | if 23 > unsafe { nil } {
| ^
8 | println('hey')
9 | }
9 changes: 9 additions & 0 deletions vlib/v/checker/tests/nil_compare_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
a := [12, 34, 56]

if a != unsafe { nil } {
println(a)
}

if 23 > unsafe { nil } {
println('hey')
}
Loading