From 2d97f16a3d2354a26b3e1c0a2e3593f3b6e2af40 Mon Sep 17 00:00:00 2001 From: shove Date: Sun, 7 Jan 2024 04:31:47 +0800 Subject: [PATCH] checker: fix option mismatch checking on array initializations (fix #20409) (#20415) --- vlib/v/checker/containers.v | 14 +++++++++++++ ...array_init_element_option_mismatch_err.out | 20 +++++++++++++++++++ .../array_init_element_option_mismatch_err.vv | 13 ++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 vlib/v/checker/tests/array_init_element_option_mismatch_err.out create mode 100644 vlib/v/checker/tests/array_init_element_option_mismatch_err.vv diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 4e7de6e9c13e72..d9c98408623c61 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -212,6 +212,20 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { c.check_expected(typ, elem_type) or { c.error('invalid array element: ${err.msg()}', expr.pos()) } + if !elem_type.has_flag(.option) + && (typ.has_flag(.option) || typ.idx() == ast.none_type_idx) { + typ_str, elem_type_str := c.get_string_names_of(typ, elem_type) + if typ.idx() == ast.none_type_idx { + c.error('cannot use `${typ_str}` as `${elem_type_str}`', expr.pos()) + } else { + c.error('cannot use `${typ_str}` as `${elem_type_str}`, it must be unwrapped first', + expr.pos()) + } + } else if elem_type.has_flag(.option) && !typ.has_flag(.option) + && typ.idx() != ast.none_type_idx && !expr.is_pure_literal() { + typ_str, elem_type_str := c.get_string_names_of(typ, elem_type) + c.error('cannot use `${typ_str}` as `${elem_type_str}`', expr.pos()) + } } } if node.is_fixed { diff --git a/vlib/v/checker/tests/array_init_element_option_mismatch_err.out b/vlib/v/checker/tests/array_init_element_option_mismatch_err.out new file mode 100644 index 00000000000000..d23e692088fd8d --- /dev/null +++ b/vlib/v/checker/tests/array_init_element_option_mismatch_err.out @@ -0,0 +1,20 @@ +vlib/v/checker/tests/array_init_element_option_mismatch_err.vv:8:11: error: cannot use `?string` as `string`, it must be unwrapped first + 6 | fn main() { + 7 | str := ?string(none) + 8 | _ = ['', str] + | ~~~ + 9 | + 10 | foo := Foo{} +vlib/v/checker/tests/array_init_element_option_mismatch_err.vv:11:18: error: cannot use `?string` as `string`, it must be unwrapped first + 9 | + 10 | foo := Foo{} + 11 | _ = [foo.a, foo.b] + | ^ + 12 | _ = [foo.b, foo.a] + 13 | } +vlib/v/checker/tests/array_init_element_option_mismatch_err.vv:12:18: error: cannot use `string` as `?string` + 10 | foo := Foo{} + 11 | _ = [foo.a, foo.b] + 12 | _ = [foo.b, foo.a] + | ^ + 13 | } diff --git a/vlib/v/checker/tests/array_init_element_option_mismatch_err.vv b/vlib/v/checker/tests/array_init_element_option_mismatch_err.vv new file mode 100644 index 00000000000000..646b673176f477 --- /dev/null +++ b/vlib/v/checker/tests/array_init_element_option_mismatch_err.vv @@ -0,0 +1,13 @@ +struct Foo { + a string + b ?string +} + +fn main() { + str := ?string(none) + _ = ['', str] + + foo := Foo{} + _ = [foo.a, foo.b] + _ = [foo.b, foo.a] +}