From e59115ed02e8f89995734294368f200ae0dbb38f Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 27 Oct 2024 21:54:46 +0800 Subject: [PATCH] checker: fix index expr that left is if expr (fix #22654) (#22661) --- vlib/v/checker/checker.v | 7 +++++++ .../tests/immutable_array_in_if_expr_index.out | 14 ++++++++++++++ .../tests/immutable_array_in_if_expr_index.vv | 6 ++++++ vlib/v/gen/c/if.v | 4 ++-- vlib/v/tests/indexexpr_with_if_expr_test.v | 12 ++++++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 vlib/v/checker/tests/immutable_array_in_if_expr_index.out create mode 100644 vlib/v/checker/tests/immutable_array_in_if_expr_index.vv create mode 100644 vlib/v/tests/indexexpr_with_if_expr_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b038bef8f9a189..959c8e59f919a5 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1006,6 +1006,13 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) { ast.InfixExpr { return '', expr.pos } + ast.IfExpr { + for mut branch in expr.branches { + mut last_expr := (branch.stmts.last() as ast.ExprStmt).expr + c.fail_if_immutable(mut last_expr) + } + return '', expr.pos + } else { if !expr.is_pure_literal() { c.error('unexpected expression `${expr.type_name()}`', expr.pos()) diff --git a/vlib/v/checker/tests/immutable_array_in_if_expr_index.out b/vlib/v/checker/tests/immutable_array_in_if_expr_index.out new file mode 100644 index 00000000000000..924921e5477ef2 --- /dev/null +++ b/vlib/v/checker/tests/immutable_array_in_if_expr_index.out @@ -0,0 +1,14 @@ +vlib/v/checker/tests/immutable_array_in_if_expr_index.vv:4:13: error: `array_a` is immutable, declare it with `mut` to make it mutable + 2 | array_a := [1, 2, 3] + 3 | array_b := [4, 5, 6] + 4 | (if true { array_a } else { array_b })[0] = 999 + | ~~~~~~~ + 5 | println(array_a) + 6 | } +vlib/v/checker/tests/immutable_array_in_if_expr_index.vv:4:30: error: `array_b` is immutable, declare it with `mut` to make it mutable + 2 | array_a := [1, 2, 3] + 3 | array_b := [4, 5, 6] + 4 | (if true { array_a } else { array_b })[0] = 999 + | ~~~~~~~ + 5 | println(array_a) + 6 | } diff --git a/vlib/v/checker/tests/immutable_array_in_if_expr_index.vv b/vlib/v/checker/tests/immutable_array_in_if_expr_index.vv new file mode 100644 index 00000000000000..a05ac803ca84e1 --- /dev/null +++ b/vlib/v/checker/tests/immutable_array_in_if_expr_index.vv @@ -0,0 +1,6 @@ +fn main() { + array_a := [1, 2, 3] + array_b := [4, 5, 6] + (if true { array_a } else { array_b })[0] = 999 + println(array_a) +} diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index 3024918c0455e4..d973ec62585d07 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -6,8 +6,8 @@ module c import v.ast fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool { - if node.is_expr && g.inside_ternary == 0 { - if g.is_autofree || node.typ.has_option_or_result() || node.is_comptime { + if node.is_expr && (g.inside_ternary == 0 || g.is_assign_lhs) { + if g.is_autofree || node.typ.has_option_or_result() || node.is_comptime || g.is_assign_lhs { return true } for branch in node.branches { diff --git a/vlib/v/tests/indexexpr_with_if_expr_test.v b/vlib/v/tests/indexexpr_with_if_expr_test.v new file mode 100644 index 00000000000000..862779fbae0c75 --- /dev/null +++ b/vlib/v/tests/indexexpr_with_if_expr_test.v @@ -0,0 +1,12 @@ +fn test_indexexpr_with_if_expr() { + mut array_a := [1, 2, 3] + mut array_b := [4, 5, 6] + + (if true { + array_a + } else { + array_b + })[0] = 999 + println(array_a) + assert array_a == [999, 2, 3] +}