From 27f9bc9ba0bb91998865c478f246fe31b97c2940 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 13 Mar 2022 15:53:29 +0800 Subject: [PATCH] checker: check error for match mut with immutable variable (fix #9704 #8976) (#13725) --- vlib/v/ast/ast.v | 2 +- vlib/v/ast/table.v | 4 ++-- vlib/v/checker/assign.v | 12 ++++++------ vlib/v/checker/check_types.v | 2 +- vlib/v/checker/checker.v | 17 ++++++++++------- vlib/v/checker/match.v | 6 +++++- .../tests/match_mut_with_immutable_var_err.out | 7 +++++++ .../tests/match_mut_with_immutable_var_err.vv | 10 ++++++++++ vlib/v/fmt/fmt.v | 3 ++- vlib/v/gen/c/assert.v | 2 +- vlib/v/gen/c/auto_str_methods.v | 2 +- vlib/v/gen/c/cgen.v | 11 ++++++----- vlib/v/gen/c/fn.v | 6 +++--- vlib/v/gen/c/infix_expr.v | 2 +- vlib/v/gen/js/auto_str_methods.v | 2 +- vlib/v/gen/js/deep_copy.v | 2 +- vlib/v/gen/js/js.v | 13 ++++++++----- vlib/v/gen/native/amd64.v | 12 ++++++------ vlib/v/gen/native/gen.v | 2 +- vlib/v/markused/walker.v | 6 ++++-- vlib/v/parser/assign.v | 3 ++- vlib/v/parser/parser.v | 2 +- vlib/v/tests/sumtype_assign_test.v | 2 +- vlib/v/transformer/transformer.v | 2 +- 24 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 vlib/v/checker/tests/match_mut_with_immutable_var_err.out create mode 100644 vlib/v/checker/tests/match_mut_with_immutable_var_err.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 795bf4260f..21e62e47a5 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -796,7 +796,7 @@ pub mut: } pub fn (i &Ident) var_info() IdentVar { - match mut i.info { + match i.info { IdentVar { return i.info } diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 292107dbc1..834e153bd8 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1640,7 +1640,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr mut nrt := '' mut c_nrt := '' ts := t.sym(typ) - match mut ts.info { + match ts.info { Array { mut elem_type := ts.info.elem_type mut elem_sym := t.sym(elem_type) @@ -1744,7 +1744,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr } else {} } - match mut ts.info { + match ts.info { Struct { mut info := ts.info info.is_generic = false diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index b48535e26e..f7ac0f3ac7 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -71,18 +71,18 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { return } - for i, left in node.left { - if left is ast.CallExpr { + for i, mut left in node.left { + if mut left is ast.CallExpr { // ban `foo() = 10` c.error('cannot call function `${left.name}()` on the left side of an assignment', left.pos) - } else if left is ast.PrefixExpr { + } else if mut left is ast.PrefixExpr { // ban `*foo() = 10` if left.right is ast.CallExpr && left.op == .mul { c.error('cannot dereference a function call on the left side of an assignment, use a temporary variable', left.pos) } - } else if left is ast.IndexExpr { + } else if mut left is ast.IndexExpr { if left.index is ast.RangeExpr { c.error('cannot reassign using range expression on the left side of an assignment', left.pos) @@ -99,8 +99,8 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } if node.right_types.len < node.left.len { // first type or multi return types added above old_inside_ref_lit := c.inside_ref_lit - if left is ast.Ident { - if left.info is ast.IdentVar { + if mut left is ast.Ident { + if mut left.info is ast.IdentVar { c.inside_ref_lit = c.inside_ref_lit || left.info.share == .shared_t } } diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 1fae6276c1..355a89d86d 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -821,7 +821,7 @@ pub fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr } else if arg_sym.kind in [.struct_, .interface_, .sum_type] { mut generic_types := []ast.Type{} mut concrete_types := []ast.Type{} - match mut arg_sym.info { + match arg_sym.info { ast.Struct, ast.Interface, ast.SumType { generic_types = arg_sym.info.generic_types concrete_types = arg_sym.info.concrete_types diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2ed709db80..228d2306f8 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -528,7 +528,7 @@ pub fn (mut c Checker) expand_iface_embeds(idecl &ast.InterfaceDecl, level int, } fn (mut c Checker) check_div_mod_by_zero(expr ast.Expr, op_kind token.Kind) { - match mut expr { + match expr { ast.FloatLiteral { if expr.val.f64() == 0.0 { oper := if op_kind == .div { 'division' } else { 'modulo' } @@ -1084,10 +1084,11 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { // returns name and position of variable that needs write lock // also sets `is_changed` to true (TODO update the name to reflect this?) -fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Pos) { +fn (mut c Checker) fail_if_immutable(expr_ ast.Expr) (string, token.Pos) { mut to_lock := '' // name of variable that needs lock mut pos := token.Pos{} // and its position mut explicit_lock_needed := false + mut expr := unsafe { expr_ } match mut expr { ast.CastExpr { // TODO @@ -1878,7 +1879,8 @@ fn (mut c Checker) check_loop_label(label string, pos token.Pos) { c.loop_label = label } -fn (mut c Checker) stmt(node ast.Stmt) { +fn (mut c Checker) stmt(node_ ast.Stmt) { + mut node := unsafe { node_ } $if trace_checker ? { ntype := typeof(node).replace('v.ast.', '') eprintln('checking: ${c.file.path:-30} | pos: ${node.pos.line_str():-39} | node: $ntype | $node') @@ -2178,7 +2180,7 @@ fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) { } fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) { - match mut arg { + match arg { ast.AsmAlias {} ast.AsmAddressing { if arg.scale !in [-1, 1, 2, 4, 8] { @@ -2449,12 +2451,13 @@ pub fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type { } // TODO node must be mut -pub fn (mut c Checker) expr(node ast.Expr) ast.Type { +pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type { c.expr_level++ defer { c.expr_level-- } + mut node := unsafe { node_ } if c.expr_level > checker.expr_level_cutoff_limit { c.error('checker: too many expr levels: $c.expr_level ', node.pos()) return ast.void_type @@ -3090,7 +3093,7 @@ pub fn (mut c Checker) ident(mut node ast.Ident) ast.Type { if node.tok_kind == .assign && node.is_mut { c.error('`mut` not allowed with `=` (use `:=` to declare a variable)', node.pos) } - if obj := node.scope.find(node.name) { + if mut obj := node.scope.find(node.name) { match mut obj { ast.GlobalField { node.kind = .global @@ -3173,7 +3176,7 @@ pub fn (mut c Checker) ident(mut node ast.Ident) ast.Type { else if !name.contains('.') && node.mod != 'builtin' { name = '${node.mod}.$node.name' } - if obj := c.file.global_scope.find(name) { + if mut obj := c.file.global_scope.find(name) { match mut obj { ast.ConstField { if !(obj.is_pub || obj.mod == c.mod || c.pref.is_test) { diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index 36cd435118..b6371783ff 100644 --- a/vlib/v/checker/match.v +++ b/vlib/v/checker/match.v @@ -23,6 +23,10 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type { // we setting this here rather than at the end of the method // since it is used in c.match_exprs() it saves checking twice node.cond_type = ast.mktyp(cond_type) + if (node.cond is ast.Ident && (node.cond as ast.Ident).is_mut) + || (node.cond is ast.SelectorExpr && (node.cond as ast.SelectorExpr).is_mut) { + c.fail_if_immutable(node.cond) + } c.ensure_type_exists(node.cond_type, node.pos) or { return ast.void_type } c.check_expr_opt_call(node.cond, cond_type) cond_type_sym := c.table.sym(cond_type) @@ -307,7 +311,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym } } } else { - match mut cond_type_sym.info { + match cond_type_sym.info { ast.SumType { for v in cond_type_sym.info.variants { v_str := c.table.type_to_str(v) diff --git a/vlib/v/checker/tests/match_mut_with_immutable_var_err.out b/vlib/v/checker/tests/match_mut_with_immutable_var_err.out new file mode 100644 index 0000000000..2714c5bca7 --- /dev/null +++ b/vlib/v/checker/tests/match_mut_with_immutable_var_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/match_mut_with_immutable_var_err.vv:5:12: error: `i` is immutable, declare it with `mut` to make it mutable + 3 | fn main() { + 4 | i := Int(0) + 5 | match mut i { + | ^ + 6 | int { i = 1 } + 7 | byte { i = 2 } diff --git a/vlib/v/checker/tests/match_mut_with_immutable_var_err.vv b/vlib/v/checker/tests/match_mut_with_immutable_var_err.vv new file mode 100644 index 0000000000..56a5760808 --- /dev/null +++ b/vlib/v/checker/tests/match_mut_with_immutable_var_err.vv @@ -0,0 +1,10 @@ +type Int = byte | int + +fn main() { + i := Int(0) + match mut i { + int { i = 1 } + byte { i = 2 } + } + println(i) +} diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 7d90e8ce8e..cee30af7df 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -505,7 +505,8 @@ fn stmt_is_single_line(stmt ast.Stmt) bool { //=== General Expr-related methods and helpers ===// -pub fn (mut f Fmt) expr(node ast.Expr) { +pub fn (mut f Fmt) expr(node_ ast.Expr) { + mut node := unsafe { node_ } if f.is_debug { eprintln('expr: ${node.pos():-42} | node: ${node.type_name():-20} | $node.str()') } diff --git a/vlib/v/gen/c/assert.v b/vlib/v/gen/c/assert.v index 24f08d3d44..0d236f5807 100644 --- a/vlib/v/gen/c/assert.v +++ b/vlib/v/gen/c/assert.v @@ -107,7 +107,7 @@ fn (mut g Gen) gen_assert_metainfo(node ast.AssertStmt) string { g.writeln('\t${metaname}.fn_name = ${ctoslit(fn_name)};') metasrc := cnewlines(ctoslit(src)) g.writeln('\t${metaname}.src = $metasrc;') - match mut node.expr { + match node.expr { ast.InfixExpr { expr_op_str := ctoslit(node.expr.op.str()) expr_left_str := cnewlines(ctoslit(node.expr.left.str())) diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index cba6fd9c9d..982a3cf3e8 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -178,7 +178,7 @@ fn (mut g Gen) final_gen_str(typ StrType) { g.gen_str_for_option(typ.typ, styp, str_fn_name) return } - match mut sym.info { + match sym.info { ast.Alias { if sym.info.is_import { g.gen_str_default(sym, styp, str_fn_name) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 4aea8788f3..dd269e29f4 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -1122,7 +1122,7 @@ fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string { sym := g.table.sym(g.unwrap_generic(typ)) mut styp := sym.cname // TODO: this needs to be removed; cgen shouldn't resolve generic types (job of checker) - match mut sym.info { + match sym.info { ast.Struct, ast.Interface, ast.SumType { if sym.info.is_generic { mut sgtyps := '_T' @@ -2733,7 +2733,7 @@ fn (mut g Gen) map_fn_ptrs(key_typ ast.TypeSymbol) (string, string, string, stri return hash_fn, key_eq_fn, clone_fn, free_fn } -fn (mut g Gen) expr(node ast.Expr) { +fn (mut g Gen) expr(node_ ast.Expr) { // println('cgen expr() line_nr=$node.pos.line_nr') old_discard_or_result := g.discard_or_result old_is_void_expr_stmt := g.is_void_expr_stmt @@ -2744,6 +2744,7 @@ fn (mut g Gen) expr(node ast.Expr) { g.discard_or_result = false } // Note: please keep the type names in the match here in alphabetical order: + mut node := unsafe { node_ } match mut node { ast.ComptimeType { g.error('g.expr(): Unhandled ComptimeType', node.pos) @@ -4550,7 +4551,7 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) { } // sym := g.table.sym(typ) mut name := sym.cname - match mut sym.info { + match sym.info { ast.Struct { if sym.info.is_generic { continue @@ -4724,7 +4725,7 @@ fn (g &Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol { } // create list of deps mut field_deps := []string{} - match mut sym.info { + match sym.info { ast.ArrayFixed { dep := g.table.sym(sym.info.elem_type).name if dep in type_names { @@ -5576,7 +5577,7 @@ static inline __shared__$interface_name ${shared_fn_name}(__shared__$cctype* x) mut name := method.name if inter_info.parent_type.has_flag(.generic) { parent_sym := g.table.sym(inter_info.parent_type) - match mut parent_sym.info { + match parent_sym.info { ast.Struct, ast.Interface, ast.SumType { name = g.generic_fn_name(parent_sym.info.concrete_types, method.name, false) diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 56b1c293fc..2e3c8ef03d 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1443,7 +1443,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) { // We do not need to declare this variable again, so just generate `t = ...` // instead of `string t = ...`, and we need to mark this variable as unused, // so that it's freed after the call. (Used tmp arg vars are not freed to avoid double frees). - if x := scope.find(t) { + if mut x := scope.find(t) { match mut x { ast.Var { x.is_used = false } else {} @@ -1491,8 +1491,8 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) { } // g.doing_autofree_tmp = true // g.write('/* postgen */') - scope := g.file.scope.innermost(node_pos) - for _, obj in scope.objects { + mut scope := g.file.scope.innermost(node_pos) + for _, mut obj in scope.objects { match mut obj { ast.Var { // if var.typ == 0 { diff --git a/vlib/v/gen/c/infix_expr.v b/vlib/v/gen/c/infix_expr.v index 752aa9e470..d844cd277a 100644 --- a/vlib/v/gen/c/infix_expr.v +++ b/vlib/v/gen/c/infix_expr.v @@ -501,7 +501,7 @@ fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) { if sym.kind == .interface_ { g.write('_typ $cmp_op ') // `_Animal_Dog_index` - sub_type := match mut node.right { + sub_type := match node.right { ast.TypeNode { node.right.typ } ast.None { g.table.type_idxs['None__'] } else { ast.Type(0) } diff --git a/vlib/v/gen/js/auto_str_methods.v b/vlib/v/gen/js/auto_str_methods.v index 14c7fdf4ef..39fc79516d 100644 --- a/vlib/v/gen/js/auto_str_methods.v +++ b/vlib/v/gen/js/auto_str_methods.v @@ -59,7 +59,7 @@ fn (mut g JsGen) final_gen_str(typ StrType) { g.gen_str_for_option(typ.typ, styp, str_fn_name) return } - match mut sym.info { + match sym.info { ast.Alias { if sym.info.is_import { g.gen_str_default(sym, styp, str_fn_name) diff --git a/vlib/v/gen/js/deep_copy.v b/vlib/v/gen/js/deep_copy.v index b892d2f4ca..9e20095820 100644 --- a/vlib/v/gen/js/deep_copy.v +++ b/vlib/v/gen/js/deep_copy.v @@ -206,7 +206,7 @@ fn (mut g JsGen) final_gen_copy(typ StrType) { } else {} } - match mut sym.info { + match sym.info { ast.Alias { g.gen_copy_for_alias(sym.info, styp, copy_fn_name) } diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index b8ab23744e..33dc2d3e6b 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -641,8 +641,9 @@ fn (mut g JsGen) gen_alias_type_decl(node ast.AliasTypeDecl) { g.writeln('function ${name}(val) { return val; }') } -fn (mut g JsGen) stmt_no_semi(node ast.Stmt) { +fn (mut g JsGen) stmt_no_semi(node_ ast.Stmt) { g.stmt_start_pos = g.out.len + mut node := unsafe { node_ } match mut node { ast.EmptyStmt {} ast.AsmStmt { @@ -744,8 +745,9 @@ fn (mut g JsGen) stmt_no_semi(node ast.Stmt) { } } -fn (mut g JsGen) stmt(node ast.Stmt) { +fn (mut g JsGen) stmt(node_ ast.Stmt) { g.stmt_start_pos = g.out.len + mut node := unsafe { node_ } match mut node { ast.EmptyStmt {} ast.AsmStmt { @@ -853,8 +855,9 @@ fn (mut g JsGen) stmt(node ast.Stmt) { } } -fn (mut g JsGen) expr(node ast.Expr) { +fn (mut g JsGen) expr(node_ ast.Expr) { // Note: please keep the type names in the match here in alphabetical order: + mut node := unsafe { node_ } match mut node { ast.ComptimeType { verror('not yet implemented') @@ -1128,7 +1131,7 @@ fn (mut g JsGen) gen_assert_metainfo(node ast.AssertStmt) string { metasrc := src g.writeln('${metaname}.src = "$metasrc"') - match mut node.expr { + match node.expr { ast.InfixExpr { expr_op_str := node.expr.op.str() expr_left_str := node.expr.left.str() @@ -1594,7 +1597,7 @@ fn (mut g JsGen) gen_expr_stmt_no_semi(it ast.ExprStmt) { fn (mut g JsGen) cc_type(typ ast.Type, is_prefix_struct bool) string { sym := g.table.sym(g.unwrap_generic(typ)) mut styp := sym.cname.replace('>', '').replace('<', '') - match mut sym.info { + match sym.info { ast.Struct, ast.Interface, ast.SumType { if sym.info.is_generic { mut sgtyps := '_T' diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index 85e0dbc62c..9f047968db 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -1209,13 +1209,13 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { if node.left is ast.InfixExpr { g.n_error('only simple expressions are supported right now (not more than 2 operands)') } - match mut node.left { + match node.left { ast.Ident { g.mov_var_to_reg(.eax, g.get_var_offset(node.left.name)) } else {} } - if mut node.right is ast.Ident { + if node.right is ast.Ident { var_offset := g.get_var_offset(node.right.name) match node.op { .plus { g.add8_var(.eax, var_offset) } @@ -1409,9 +1409,9 @@ fn (mut g Gen) cjmp_op(op token.Kind) int { } fn (mut g Gen) condition(infix_expr ast.InfixExpr, neg bool) int { - match mut infix_expr.left { + match infix_expr.left { ast.IntegerLiteral { - match mut infix_expr.right { + match infix_expr.right { ast.IntegerLiteral { // 3 < 4 a0 := infix_expr.left.val.int() @@ -1435,7 +1435,7 @@ fn (mut g Gen) condition(infix_expr ast.InfixExpr, neg bool) int { } } ast.Ident { - match mut infix_expr.right { + match infix_expr.right { ast.IntegerLiteral { // var < 4 lit := infix_expr.right as ast.IntegerLiteral @@ -1515,7 +1515,7 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) { infix_expr := node.cond as ast.InfixExpr mut jump_addr := 0 // location of `jne *00 00 00 00*` start := g.pos() - match mut infix_expr.left { + match infix_expr.left { ast.Ident { match infix_expr.right { ast.Ident { diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index e42b3d648d..e599b0278b 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -486,7 +486,7 @@ fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) { match cond { ast.InfixExpr { // g.infix_expr(node.cond) - match mut cond.left { + match cond.left { ast.Ident { lit := cond.right as ast.IntegerLiteral g.cmp_var(cond.left.name, lit.val.int()) diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index 26c659aedf..67e7447e74 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -96,7 +96,8 @@ pub fn (mut w Walker) mark_markused_globals() { } } -pub fn (mut w Walker) stmt(node ast.Stmt) { +pub fn (mut w Walker) stmt(node_ ast.Stmt) { + mut node := unsafe { node_ } match mut node { ast.EmptyStmt {} ast.AsmStmt { @@ -215,7 +216,8 @@ fn (mut w Walker) exprs(exprs []ast.Expr) { } } -fn (mut w Walker) expr(node ast.Expr) { +fn (mut w Walker) expr(node_ ast.Expr) { + mut node := unsafe { node_ } match mut node { ast.EmptyExpr { // TODO make sure this doesn't happen diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index 0f6a28726c..9da40ed599 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -175,7 +175,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme mut has_cross_var := false mut is_static := false mut is_volatile := false - for i, lx in left { + for i, lx_ in left { + mut lx := unsafe { lx_ } match mut lx { ast.Ident { if op == .decl_assign { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index b8ea460c8d..c4468d242b 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -3750,7 +3750,7 @@ fn (mut p Parser) rewind_scanner_to_current_token_in_new_mode() { // returns true if `varname` is known pub fn (mut p Parser) mark_var_as_used(varname string) bool { - if obj := p.scope.find(varname) { + if mut obj := p.scope.find(varname) { match mut obj { ast.Var { obj.is_used = true diff --git a/vlib/v/tests/sumtype_assign_test.v b/vlib/v/tests/sumtype_assign_test.v index e44ae1b9a9..7b726f49b3 100644 --- a/vlib/v/tests/sumtype_assign_test.v +++ b/vlib/v/tests/sumtype_assign_test.v @@ -27,7 +27,7 @@ fn test_sumtype_assign() { text: 'baz' } mut results := []string{} - for a in arr { + for mut a in arr { match mut a { Bar, Baz { a.text = 'I am ' + a.text diff --git a/vlib/v/transformer/transformer.v b/vlib/v/transformer/transformer.v index c7032c62f0..6239237dfc 100644 --- a/vlib/v/transformer/transformer.v +++ b/vlib/v/transformer/transformer.v @@ -401,7 +401,7 @@ pub fn (mut t Transformer) expr_stmt_match_expr(mut node ast.MatchExpr) ast.Expr for mut expr in branch.exprs { expr = t.expr(mut expr) - match mut cond { + match cond { ast.BoolLiteral { if expr is ast.BoolLiteral { if cond.val == (expr as ast.BoolLiteral).val {