From 29ce5b83acf084e6e3d752a0c51ad2119da2c8f9 Mon Sep 17 00:00:00 2001 From: Swastik Date: Tue, 14 Jan 2025 01:55:21 +0530 Subject: [PATCH] checker: check if unwrapped `m[key]` if m is `Option` --- vlib/v/checker/checker.v | 3 +++ vlib/v/checker/tests/option_map_err.out | 6 ++++++ vlib/v/checker/tests/selector_expr_opt_map_get_err.out | 6 ++++++ vlib/v/checker/tests/selector_expr_opt_map_get_err.vv | 9 +++++++++ 4 files changed, 24 insertions(+) create mode 100644 vlib/v/checker/tests/selector_expr_opt_map_get_err.out create mode 100644 vlib/v/checker/tests/selector_expr_opt_map_get_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4a1776134f69c1..cd357765bcb51a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -4914,6 +4914,9 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type { } else if node.left is ast.CallExpr { c.error('type `?${typ_sym.name}` is an Option, it must be unwrapped with `func()?`, or use `func() or {default}`', node.left.pos()) + } else if node.left is ast.SelectorExpr && node.left.or_block.kind == .absent { + c.error('type `?${typ_sym.name}` is an Option, it must be unwrapped first; use `struct.var?[]` to do it', + node.left.pos()) } } else if typ.has_flag(.result) { c.error('type `!${typ_sym.name}` is a Result, it does not support indexing', node.left.pos()) diff --git a/vlib/v/checker/tests/option_map_err.out b/vlib/v/checker/tests/option_map_err.out index cc6bd6622c0fe8..8a4e04f8ce5bf4 100644 --- a/vlib/v/checker/tests/option_map_err.out +++ b/vlib/v/checker/tests/option_map_err.out @@ -1,3 +1,9 @@ +vlib/v/checker/tests/option_map_err.vv:22:13: error: type `?map[string]f64` is an Option, it must be unwrapped first; use `struct.var?[]` to do it + 20 | } + 21 | } + 22 | assert op2.opmap['1'] == 1.0 + | ~~~~~ + 23 | } vlib/v/checker/tests/option_map_err.vv:22:13: error: field `opmap` is an Option, so it should have either an `or {}` block, or `?` at the end 20 | } 21 | } diff --git a/vlib/v/checker/tests/selector_expr_opt_map_get_err.out b/vlib/v/checker/tests/selector_expr_opt_map_get_err.out new file mode 100644 index 00000000000000..470fb09b6d0848 --- /dev/null +++ b/vlib/v/checker/tests/selector_expr_opt_map_get_err.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/selector_expr_opt_map_get_err.vv:8:9: error: type `?map[string]string` is an Option, it must be unwrapped first; use `struct.var?[]` to do it + 6 | fn main() { + 7 | x := Abc{} + 8 | _ := x.m['test'] or { 'test' } + | ^ + 9 | } diff --git a/vlib/v/checker/tests/selector_expr_opt_map_get_err.vv b/vlib/v/checker/tests/selector_expr_opt_map_get_err.vv new file mode 100644 index 00000000000000..68e6a4dbe34915 --- /dev/null +++ b/vlib/v/checker/tests/selector_expr_opt_map_get_err.vv @@ -0,0 +1,9 @@ +struct Abc { +mut: + m ?map[string]string +} + +fn main() { + x := Abc{} + _ := x.m['test'] or { 'test' } +}