From 4fa315edc2d9d355d2f724ce99c2c0cc04113601 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 18 Feb 2021 03:44:28 +0800 Subject: [PATCH] checker: fix for _, mut j in array (#8785) --- vlib/v/ast/ast.v | 14 ++++-- vlib/v/checker/checker.v | 15 +++++-- vlib/v/tests/mut_test.v | 94 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 6 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 2ef61268a9..99776a2159 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1537,12 +1537,20 @@ pub struct Table { } pub fn (expr Expr) is_mut_ident() bool { - if expr is Ident { - if expr.obj is Var { - if expr.obj.is_auto_deref { + match expr { + Ident { + if expr.obj is Var { + if expr.obj.is_auto_deref { + return true + } + } + } + PrefixExpr { + if expr.op == .amp && expr.right.is_mut_ident() { return true } } + else {} } return false } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d862f7d79a..02b1c99dd6 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1406,7 +1406,11 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type { // need to return `array_xxx` instead of `array` // in ['clone', 'str'] { call_expr.receiver_type = left_type.to_ptr() - call_expr.return_type = call_expr.receiver_type.set_nr_muls(0) + if call_expr.left.is_mut_ident() { + call_expr.return_type = left_type.deref() + } else { + call_expr.return_type = call_expr.receiver_type.set_nr_muls(0) + } } else if method_name == 'sort' { call_expr.return_type = table.void_type } else if method_name == 'contains' { @@ -1422,7 +1426,11 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type { if method_name[0] == `m` { c.fail_if_immutable(call_expr.left) } - ret_type = left_type + if call_expr.left.is_mut_ident() { + ret_type = left_type.deref() + } else { + ret_type = left_type + } } 'keys' { info := left_type_sym.info as table.Map @@ -2849,7 +2857,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { } } } - if !is_blank_ident && right_sym.kind != .placeholder && left_sym.kind != .interface_ { + if !is_blank_ident && !right.is_mut_ident() && right_sym.kind != .placeholder + && left_sym.kind != .interface_ { // Dual sides check (compatibility check) c.check_expected(right_type_unwrapped, left_type_unwrapped) or { c.error('cannot assign to `$left`: $err', right.position()) diff --git a/vlib/v/tests/mut_test.v b/vlib/v/tests/mut_test.v index 4859740dc9..3a3d56d059 100644 --- a/vlib/v/tests/mut_test.v +++ b/vlib/v/tests/mut_test.v @@ -254,3 +254,97 @@ fn test_mut_12() { mut arr := [[0, 0]] foo3(mut arr) } + +struct Foo { +mut: + foo int +} + +fn foo4(mut f Foo) { + f2 := &f + f.foo = 100 + println(f.foo) + println(f2.foo) + assert f.foo == 100 + assert f2.foo == 100 +} + +fn test_mut_13() { + mut f := Foo{foo: 1} + foo4(mut f) +} + +fn foo5(mut arr []int) { + arr2 := &arr + arr[0] = 0 + println(arr[0]) // 0 + assert arr[0] == 0 + unsafe { + println(arr2[0]) // 0 + assert arr2[0] == 0 + } +} + +fn test_mut_14() { + mut arr := [1,2,3] + foo5(mut arr) +} + +fn foo6(mut arr [3]int) { + arr2 := &arr + arr[0] = 0 + println(arr[0]) // 0 + assert arr[0] == 0 + unsafe { + println(arr2[0]) // 0 + assert arr2[0] == 0 + } +} + +fn test_mut_15() { + mut arr := [1,2,3]! + foo6(mut arr) +} + +fn foo7(mut m map[string]int) { + m2 := &m + m['one'] = 1 + println(m['one']) // 1 + assert m['one'] == 1 + unsafe { + println(m2['one']) // 1 + assert m2['one'] == 1 + } +} + +fn test_mut_16() { + mut m := map{'one': 100, 'two': 2} + foo7(mut m) +} + +fn test_mut_17() { + mut arr := [map{'foo':1}] + for _, mut j in arr { + mut k := j.clone() + j['foo'] = 0 + unsafe {k['foo'] = 10} + println(j) + println(k) + assert j == {'foo': 0} + assert k == {'foo': 10} + } +} + +fn foo8(mut a [1]int) { + a2 := a + a[0] = 100 + println(a) + println(a2) + assert '$a' == '[100]' + assert '$a2' == '[1]' +} + +fn test_mut_18() { + mut a := [1]! + foo8(mut a) +}