checker: fix for _, mut j in array (#8785)

pull/8811/head
yuyi 2021-02-18 03:44:28 +08:00 committed by GitHub
parent 600f6ad2a0
commit 4fa315edc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 117 additions and 6 deletions

View File

@ -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
}

View File

@ -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())

View File

@ -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)
}