From 86536e452e6248056666c750668334c7da87202e Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 30 Mar 2025 20:16:16 -0300 Subject: [PATCH] checker: fix check for pushing on an unwrapped option array (fix #24073) (#24093) --- vlib/v/checker/infix.v | 3 +++ vlib/v/checker/tests/option_array_push.out | 7 +++++++ vlib/v/checker/tests/option_array_push.vv | 18 ++++++++++++++++++ .../tests/wrong_shift_left_option_err.out | 14 ++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 vlib/v/checker/tests/option_array_push.out create mode 100644 vlib/v/checker/tests/option_array_push.vv diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index de8f02c36..d69a8d9c3 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -57,6 +57,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } // `arr << if n > 0 { 10 } else { 11 }` set the right c.expected_type if node.op == .left_shift && c.table.sym(left_type).kind == .array { + if left_type.has_flag(.option) { + c.error('cannot push to Option array that was not unwrapped first', node.left.pos()) + } c.markused_infiexpr(!c.is_builtin_mod && c.mod != 'strings') if mut node.right is ast.IfExpr { if node.right.is_expr && node.right.branches.len > 0 { diff --git a/vlib/v/checker/tests/option_array_push.out b/vlib/v/checker/tests/option_array_push.out new file mode 100644 index 000000000..4c2296d30 --- /dev/null +++ b/vlib/v/checker/tests/option_array_push.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/option_array_push.vv:13:5: error: cannot push to Option array that was not unwrapped first + 11 | fn my_func(args Struct2) { + 12 | mut s1 := args.Struct1 + 13 | s1.strings << ['hi'] + | ~~~~~~~ + 14 | } + 15 | diff --git a/vlib/v/checker/tests/option_array_push.vv b/vlib/v/checker/tests/option_array_push.vv new file mode 100644 index 000000000..bd99293d3 --- /dev/null +++ b/vlib/v/checker/tests/option_array_push.vv @@ -0,0 +1,18 @@ +pub struct Struct1 { +pub mut: + strings ?[]string +} + +@[params] +pub struct Struct2 { + Struct1 +} + +fn my_func(args Struct2) { + mut s1 := args.Struct1 + s1.strings << ['hi'] +} + +s2 := Struct2{} + +my_func(s2) diff --git a/vlib/v/checker/tests/wrong_shift_left_option_err.out b/vlib/v/checker/tests/wrong_shift_left_option_err.out index 7f6595d2b..abd9f813d 100644 --- a/vlib/v/checker/tests/wrong_shift_left_option_err.out +++ b/vlib/v/checker/tests/wrong_shift_left_option_err.out @@ -1,3 +1,10 @@ +vlib/v/checker/tests/wrong_shift_left_option_err.vv:7:2: error: cannot push to Option array that was not unwrapped first + 5 | fn main() { + 6 | mut a := ?[]SomeStruct([SomeStruct{}, SomeStruct{}]) // struct type + 7 | a << []SomeStruct{len: 20} + | ^ + 8 | mut b := ?[]int([2, 8]) // primitive type + 9 | b << [1, 3, 4] vlib/v/checker/tests/wrong_shift_left_option_err.vv:7:4: error: unwrapped Option cannot be used in an infix expression 5 | fn main() { 6 | mut a := ?[]SomeStruct([SomeStruct{}, SomeStruct{}]) // struct type @@ -5,6 +12,13 @@ vlib/v/checker/tests/wrong_shift_left_option_err.vv:7:4: error: unwrapped Option | ~~ 8 | mut b := ?[]int([2, 8]) // primitive type 9 | b << [1, 3, 4] +vlib/v/checker/tests/wrong_shift_left_option_err.vv:9:2: error: cannot push to Option array that was not unwrapped first + 7 | a << []SomeStruct{len: 20} + 8 | mut b := ?[]int([2, 8]) // primitive type + 9 | b << [1, 3, 4] + | ^ + 10 | dump(a?.len) + 11 | dump(b) vlib/v/checker/tests/wrong_shift_left_option_err.vv:9:4: error: unwrapped Option cannot be used in an infix expression 7 | a << []SomeStruct{len: 20} 8 | mut b := ?[]int([2, 8]) // primitive type -- 2.39.5