Skip to content

Commit ceac4ba

Browse files
authored
checker: add infix checks for nil (#22045)
1 parent acf04a2 commit ceac4ba

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

vlib/v/checker/infix.v

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,37 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
197197
}
198198
}
199199
}
200+
201+
// Do not allow comparing nil to non-pointers
202+
if node.left.is_nil() {
203+
mut final_type := right_type
204+
if mut right_sym.info is ast.Alias
205+
&& right_sym.info.parent_type.is_any_kind_of_pointer() {
206+
final_type = right_sym.info.parent_type
207+
}
208+
if !final_type.is_any_kind_of_pointer() && (right_final_sym.kind != .function
209+
|| (right_final_sym.language != .c && right_final_sym.kind == .placeholder))
210+
&& !right_final_sym.is_heap() {
211+
rt := c.table.sym(right_type).name
212+
c.error('cannot compare with `nil` because `${rt}` is not a pointer',
213+
node.pos)
214+
}
215+
}
216+
217+
if node.right.is_nil() {
218+
mut final_type := left_type
219+
if mut left_sym.info is ast.Alias
220+
&& left_sym.info.parent_type.is_any_kind_of_pointer() {
221+
final_type = left_sym.info.parent_type
222+
}
223+
if !final_type.is_any_kind_of_pointer() && (left_final_sym.kind != .function
224+
|| (left_final_sym.language != .c && left_final_sym.kind == .placeholder))
225+
&& !left_final_sym.is_heap() {
226+
lt := c.table.sym(left_type).name
227+
c.error('cannot compare with `nil` because `${lt}` is not a pointer',
228+
node.pos)
229+
}
230+
}
200231
}
201232
.key_in, .not_in {
202233
match right_final_sym.kind {
@@ -542,6 +573,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
542573
c.error('unwrapped Option cannot be compared in an infix expression',
543574
opt_comp_pos)
544575
}
576+
if node.left.is_nil() || node.right.is_nil() {
577+
c.error('cannot use `${node.op.str()}` with `nil`', node.pos)
578+
}
545579
}
546580
.key_like {
547581
node.promoted_type = ast.bool_type
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
vlib/v/checker/tests/nil_compare_err.vv:3:6: error: cannot compare with `nil` because `[]int` is not a pointer
2+
1 | a := [12, 34, 56]
3+
2 |
4+
3 | if a != unsafe { nil } {
5+
| ~~
6+
4 | println(a)
7+
5 | }
8+
vlib/v/checker/tests/nil_compare_err.vv:7:7: error: cannot use `>` with `nil`
9+
5 | }
10+
6 |
11+
7 | if 23 > unsafe { nil } {
12+
| ^
13+
8 | println('hey')
14+
9 | }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
a := [12, 34, 56]
2+
3+
if a != unsafe { nil } {
4+
println(a)
5+
}
6+
7+
if 23 > unsafe { nil } {
8+
println('hey')
9+
}

0 commit comments

Comments
 (0)