From d30e1a52e21bd7e23a23cd2bcff6a8aed18db314 Mon Sep 17 00:00:00 2001 From: Swastik Baranwal Date: Wed, 5 Apr 2023 13:50:42 +0530 Subject: [PATCH] checker: disallow unwrapped option/result with `in` operator (#17875) --- vlib/v/checker/infix.v | 12 ++++++++ ...wrapped_option_result_in_operation_err.out | 28 +++++++++++++++++++ ...nwrapped_option_result_in_operation_err.vv | 15 ++++++++++ 3 files changed, 55 insertions(+) create mode 100644 vlib/v/checker/tests/unwrapped_option_result_in_operation_err.out create mode 100644 vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 1b46d47fb8..4202a7eb4c 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -195,6 +195,18 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { node.pos) } } + if mut node.left is ast.CallExpr { + if node.left.return_type.has_flag(.option) + || node.left.return_type.has_flag(.result) { + option_or_result := if node.left.return_type.has_flag(.option) { + 'option' + } else { + 'result' + } + c.error('unwrapped ${option_or_result} cannot be used with `${node.op.str()}`', + left_pos) + } + } node.promoted_type = ast.bool_type return ast.bool_type } diff --git a/vlib/v/checker/tests/unwrapped_option_result_in_operation_err.out b/vlib/v/checker/tests/unwrapped_option_result_in_operation_err.out new file mode 100644 index 0000000000..6b2e8d7a58 --- /dev/null +++ b/vlib/v/checker/tests/unwrapped_option_result_in_operation_err.out @@ -0,0 +1,28 @@ +vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv:3:6: error: unwrapped result cannot be used with `!in` + 1 | fn main() { + 2 | list := ['string'] + 3 | _ = return_string_or_error() !in list + | ~~~~~~~~~~~~~~~~~~~~~~~~ + 4 | _ = return_string_or_error() in list + 5 | _ = return_string_or_none() in list +vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv:4:6: error: unwrapped result cannot be used with `in` + 2 | list := ['string'] + 3 | _ = return_string_or_error() !in list + 4 | _ = return_string_or_error() in list + | ~~~~~~~~~~~~~~~~~~~~~~~~ + 5 | _ = return_string_or_none() in list + 6 | _ = return_string_or_error() !in list +vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv:5:6: error: unwrapped option cannot be used with `in` + 3 | _ = return_string_or_error() !in list + 4 | _ = return_string_or_error() in list + 5 | _ = return_string_or_none() in list + | ~~~~~~~~~~~~~~~~~~~~~~~ + 6 | _ = return_string_or_error() !in list + 7 | } +vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv:6:6: error: unwrapped result cannot be used with `!in` + 4 | _ = return_string_or_error() in list + 5 | _ = return_string_or_none() in list + 6 | _ = return_string_or_error() !in list + | ~~~~~~~~~~~~~~~~~~~~~~~~ + 7 | } + 8 | diff --git a/vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv b/vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv new file mode 100644 index 0000000000..f702d85152 --- /dev/null +++ b/vlib/v/checker/tests/unwrapped_option_result_in_operation_err.vv @@ -0,0 +1,15 @@ +fn main() { + list := ['string'] + _ = return_string_or_error() !in list + _ = return_string_or_error() in list + _ = return_string_or_none() in list + _ = return_string_or_error() !in list +} + +fn return_string_or_error() !string { + return '' +} + +fn return_string_or_none() ?string { + return '' +}