From b5c1ea44dc38d8a074407ab1de34c0bae08bdc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Mon, 17 Aug 2020 21:11:11 +0200 Subject: [PATCH] all: fix mutability after if-smartcast (#6129) --- vlib/v/checker/checker.v | 10 ++++++---- vlib/v/gen/cgen.v | 5 +++++ vlib/v/parser/if_match.v | 2 +- vlib/v/tests/if_smartcast_test.v | 25 ++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2ab78ca7b3..fbf23c45ab 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2550,7 +2550,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type { return info.typ } else if ident.kind == .unresolved { // first use - start_scope := c.file.scope.innermost(ident.pos.pos) + start_scope := c.file.scope.innermost(ident.pos.pos + 1) if obj1 := start_scope.find(ident.name) { match mut obj1 as obj { ast.GlobalDecl { @@ -2985,8 +2985,11 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { left_sym := c.table.get_type_symbol(infix.left_type) if left_sym.kind == .sum_type && branch.left_as_name.len > 0 { mut is_mut := false - if infix.left is ast.Ident { - is_mut = (infix.left as ast.Ident).is_mut + mut scope := c.file.scope.innermost(branch.body_pos.pos) + if infix.left is ast.Ident as infix_left { + if var := scope.find_var(infix_left.name) { + is_mut = var.is_mut + } } else if infix.left is ast.SelectorExpr { selector := infix.left as ast.SelectorExpr field := c.table.struct_find_field(left_sym, selector.field_name) or { @@ -2994,7 +2997,6 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type { } is_mut = field.is_mut } - mut scope := c.file.scope.innermost(branch.body_pos.pos) scope.register(branch.left_as_name, ast.Var{ name: branch.left_as_name typ: right_expr.typ.to_ptr() diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 0758500f87..26921c3b43 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1826,6 +1826,11 @@ fn (mut g Gen) expr(node ast.Expr) { g.write(')') } else if sym.kind == .sum_type { g.expr_with_cast(node.expr, node.expr_type, node.typ) + } else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as table.Struct).is_typedef { + styp := g.typ(node.typ) + g.write('*(($styp *)(&') + g.expr(node.expr) + g.write('))') } else { // styp := g.table.Type_to_str(it.typ) styp := g.typ(node.typ) diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index ca40c69531..1c188419af 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -118,7 +118,7 @@ fn (mut p Parser) if_expr() ast.IfExpr { cond: cond stmts: stmts pos: start_pos.extend(end_pos) - body_pos: body_pos.extend(p.tok.position()) + body_pos: body_pos.extend(p.prev_tok.position()) comments: comments left_as_name: left_as_name } diff --git a/vlib/v/tests/if_smartcast_test.v b/vlib/v/tests/if_smartcast_test.v index 30db28e844..93fc576b4d 100644 --- a/vlib/v/tests/if_smartcast_test.v +++ b/vlib/v/tests/if_smartcast_test.v @@ -51,7 +51,7 @@ fn test_mutable_with_struct() { mut x := Test{Abc{'test'}} if x.abc is Abc as test { mut ttt := test - assert u64(ttt) == u64(ttt) + assert u64(ttt) == u64(ttt) ttt.val = 'test' assert ttt.val == 'test' } @@ -63,3 +63,26 @@ fn test_as_cast_with_struct() { assert test.val == 'test' } } + +struct CellStr { str string } +struct CellInt { itg i64 } +struct CellFloat { flt f64 } +type Cell = CellStr | CellInt | CellFloat +fn test_mutability() { + my_str := 'the quick brown fox jumps over the lazy dog.' + my_itg := -1234567890 + my_flt := 3.14159265358979323846 + my_u32 := u32(4294967296) + cell_str := CellStr{ str: my_str } + cell_itg := CellInt{ itg: my_itg } + cell_flt := CellFloat{ flt: my_flt } + mut cell := Cell{} + cell = cell_str + if cell is CellStr { + println('$cell.str') + } + cell = cell_itg + if cell is CellInt { + println('$cell.itg') + } +}