From ceac4baf870f76f7bebc5f636507b11fc31c4148 Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Sun, 18 Aug 2024 18:45:05 +0530 Subject: [PATCH] checker: add infix checks for nil (#22045) --- vlib/v/checker/infix.v | 34 ++++++++++++++++++++++++ vlib/v/checker/tests/nil_compare_err.out | 14 ++++++++++ vlib/v/checker/tests/nil_compare_err.vv | 9 +++++++ 3 files changed, 57 insertions(+) create mode 100644 vlib/v/checker/tests/nil_compare_err.out create mode 100644 vlib/v/checker/tests/nil_compare_err.vv diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index af39ac57e..5f16baa95 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -197,6 +197,37 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } } } + + // 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 { @@ -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 diff --git a/vlib/v/checker/tests/nil_compare_err.out b/vlib/v/checker/tests/nil_compare_err.out new file mode 100644 index 000000000..fa9da352c --- /dev/null +++ b/vlib/v/checker/tests/nil_compare_err.out @@ -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 | } diff --git a/vlib/v/checker/tests/nil_compare_err.vv b/vlib/v/checker/tests/nil_compare_err.vv new file mode 100644 index 000000000..5f0088378 --- /dev/null +++ b/vlib/v/checker/tests/nil_compare_err.vv @@ -0,0 +1,9 @@ +a := [12, 34, 56] + +if a != unsafe { nil } { + println(a) +} + +if 23 > unsafe { nil } { + println('hey') +} -- 2.39.5