diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 114aa29619..8d33f9a7b1 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1418,6 +1418,7 @@ pub mut: pub struct IfGuardExpr { pub: var_name string + is_mut bool pos token.Position pub mut: expr Expr diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 7568e8fcba..544d38c567 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1893,6 +1893,9 @@ fn branch_is_single_line(b ast.IfBranch) bool { } pub fn (mut f Fmt) if_guard_expr(node ast.IfGuardExpr) { + if node.is_mut { + f.write('mut ') + } f.write(node.var_name + ' := ') f.expr(node.expr) } diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 44b275cf21..1df8311de7 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -81,10 +81,17 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { comments << p.eat_comments() mut cond := ast.empty_expr() mut is_guard := false + // `if x := opt() {` - if !is_comptime && p.peek_tok.kind == .decl_assign { + if !is_comptime && (p.peek_tok.kind == .decl_assign + || (p.tok.kind == .key_mut && p.peek_token(2).kind == .decl_assign)) { p.open_scope() is_guard = true + mut is_mut := false + if p.tok.kind == .key_mut { + is_mut = true + p.check(.key_mut) + } var_pos := p.tok.position() var_name := p.check_name() if p.scope.known_var(var_name) { @@ -96,10 +103,12 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { expr := p.expr(0) cond = ast.IfGuardExpr{ var_name: var_name + is_mut: is_mut expr: expr } p.scope.register(ast.Var{ name: var_name + is_mut: is_mut expr: cond pos: var_pos }) diff --git a/vlib/v/tests/if_guard_test.v b/vlib/v/tests/if_guard_test.v index e6866181d7..e8d36e59e1 100644 --- a/vlib/v/tests/if_guard_test.v +++ b/vlib/v/tests/if_guard_test.v @@ -106,21 +106,28 @@ fn test_chan_pop_empty() { } struct Thing { - name string +mut: + value int } -fn test_return_if_guard() { - ret := option_check('zoo') - println(ret) - assert ret == 'zs' -} - -fn option_check(name string) string { - return if thing := find_thing_by_name(name) { thing.name } else { 'safename' } -} - -fn find_thing_by_name(name string) ?&Thing { - return &Thing{ - name: 'zs' +fn maybe_a_thing() ?Thing { + return Thing{ + value: 1 + } +} + +fn test_if_guard() { + if val := maybe_a_thing() { + assert val.value == 1 + } else { + assert false + } + + if mut val := maybe_a_thing() { + assert val.value == 1 + val.value = 2 + assert val.value == 2 + } else { + assert false } }