From 1471ba4678e1296487a006e91cc794003d51d3d3 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 1 Apr 2023 18:03:42 -0300 Subject: [PATCH] checker: fix missing check for initializer with function returning options (#17820) --- vlib/v/checker/containers.v | 7 +++++++ .../v/checker/tests/array_init_option_err.out | 20 +++++++++++++++++++ vlib/v/checker/tests/array_init_option_err.vv | 14 +++++++++++++ vlib/v/checker/tests/option_fn_err.out | 13 +++++++++--- 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 vlib/v/checker/tests/array_init_option_err.out create mode 100644 vlib/v/checker/tests/array_init_option_err.vv diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 93194bf9e4..c51f7f7e2d 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -66,11 +66,18 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { default_expr := node.default_expr default_typ := c.check_expr_opt_call(default_expr, c.expr(default_expr)) node.default_type = default_typ + if !node.elem_type.has_flag(.option) && default_typ.has_flag(.option) { + c.error('cannot use unwrapped Option as initializer', default_expr.pos()) + } c.check_expected(default_typ, node.elem_type) or { c.error(err.msg(), default_expr.pos()) } } if node.has_len { + len_typ := c.check_expr_opt_call(node.len_expr, c.expr(node.len_expr)) + if len_typ.has_flag(.option) { + c.error('cannot use unwrapped Option as length', node.len_expr.pos()) + } if node.has_len && !node.has_default { elem_type_sym := c.table.sym(node.elem_type) if elem_type_sym.kind == .interface_ { diff --git a/vlib/v/checker/tests/array_init_option_err.out b/vlib/v/checker/tests/array_init_option_err.out new file mode 100644 index 0000000000..fcecf768f3 --- /dev/null +++ b/vlib/v/checker/tests/array_init_option_err.out @@ -0,0 +1,20 @@ +vlib/v/checker/tests/array_init_option_err.vv:2:38: error: cannot use unwrapped Option as initializer + 1 | fn main() { + 2 | mut arr1 := []int{len: get(), init: get()} + | ~~~~~ + 3 | dump(arr1) + 4 | +vlib/v/checker/tests/array_init_option_err.vv:5:20: error: cannot use unwrapped Option as length + 3 | dump(arr1) + 4 | + 5 | arr1 = []int{len: get(), init: get()?} + | ~~~~~ + 6 | dump(arr1) + 7 | +vlib/v/checker/tests/array_init_option_err.vv:8:34: error: cannot use unwrapped Option as initializer + 6 | dump(arr1) + 7 | + 8 | arr1 = []int{len: get()?, init: get()} + | ~~~~~ + 9 | dump(arr1) + 10 | } diff --git a/vlib/v/checker/tests/array_init_option_err.vv b/vlib/v/checker/tests/array_init_option_err.vv new file mode 100644 index 0000000000..87b3ae5cfe --- /dev/null +++ b/vlib/v/checker/tests/array_init_option_err.vv @@ -0,0 +1,14 @@ +fn main() { + mut arr1 := []int{len: get(), init: get()} + dump(arr1) + + arr1 = []int{len: get(), init: get()?} + dump(arr1) + + arr1 = []int{len: get()?, init: get()} + dump(arr1) +} + +fn get() ?int { + return 5 +} \ No newline at end of file diff --git a/vlib/v/checker/tests/option_fn_err.out b/vlib/v/checker/tests/option_fn_err.out index 803738034d..bd06ff0b54 100644 --- a/vlib/v/checker/tests/option_fn_err.out +++ b/vlib/v/checker/tests/option_fn_err.out @@ -1,9 +1,9 @@ vlib/v/checker/tests/option_fn_err.vv:40:9: error: assert can be used only with `bool` expressions, but found `bool` instead - 38 | + 38 | 39 | // assert 40 | assert bar(true) | ~~~~~~~~~ - 41 | + 41 | 42 | // struct vlib/v/checker/tests/option_fn_err.vv:45:3: error: cannot assign an Option value to a non-option struct field 43 | mut v := Data{ @@ -12,6 +12,13 @@ vlib/v/checker/tests/option_fn_err.vv:45:3: error: cannot assign an Option value | ~~~~~~~~~~~~~ 46 | opt: bar(0) 47 | } +vlib/v/checker/tests/option_fn_err.vv:56:27: error: cannot use unwrapped Option as initializer + 54 | // init + 55 | _ := [bar(0)] + 56 | _ := []int{len: 1, init: bar(0)} + | ~~~~~~ + 57 | _ := [bar(0)]! + 58 | _ := [1]int{init: bar(0)} vlib/v/checker/tests/option_fn_err.vv:60:13: error: cannot use Option or Result as index (array type `[]int`) 58 | _ := [1]int{init: bar(0)} 59 | // index @@ -38,5 +45,5 @@ vlib/v/checker/tests/option_fn_err.vv:69:18: error: type mismatch, `bar` must re 68 | println(arr.any(bar(true))) 69 | println(arr.all(bar(true))) | ~~~~~~~~~ - 70 | + 70 | 71 | match bar(0) {