checker: do not allow modifying consts via mutable refs

pull/9865/head
Alexander Medvednikov 2021-04-24 14:08:37 +03:00
parent b506d8fcc0
commit 7f5c3cc1f8
4 changed files with 43 additions and 6 deletions

View File

@ -586,3 +586,7 @@ fn test_truncate() {
assert newlen == os.file_size(filename)
os.rm(filename) or { panic(err) }
}
fn test_hostname() {
assert os.hostname().len > 2
}

View File

@ -3222,7 +3222,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
c.type_implements(right_type, left_type, right.position())
}
}
// this needs to run after the assign stmt left exprs have been run through checker so that ident.obj is set
// this needs to run after the assign stmt left exprs have been run through checker
// so that ident.obj is set
// Check `x := &y` and `mut x := <-ch`
if right_first is ast.PrefixExpr {
node := right_first
@ -3237,15 +3238,20 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
c.inside_ref_lit = (c.inside_ref_lit || node.op == .amp || is_shared)
c.expr(node.right)
c.inside_ref_lit = old_inside_ref_lit
if node.right is ast.Ident {
if node.right.obj is ast.Var {
v := node.right.obj
right_type0 = v.typ
if node.op == .amp {
if node.op == .amp {
if node.right is ast.Ident {
if node.right.obj is ast.Var {
v := node.right.obj
right_type0 = v.typ
if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe {
c.error('`$node.right.name` is immutable, cannot have a mutable reference to it',
node.pos)
}
} else if node.right.obj is ast.ConstField {
if assigned_var.is_mut && !c.inside_unsafe {
c.error('`$node.right.name` is immutable, cannot have a mutable reference to it',
node.pos)
}
}
}
}

View File

@ -0,0 +1,14 @@
g.v:9:6: warning: unused variable: `unused_var`
7 |
8 | fn main() {
9 | mut unused_var := Foo{}
| ~~~~~~~~~~
10 | unused_var = Foo{}
11 | mut c := &constant
g.v:11:14: error: `constant` is immutable, cannot have a mutable reference to it
9 | mut unused_var := Foo{}
10 | unused_var = Foo{}
11 | mut c := &constant
| ^
12 | c.value = 200
13 | }

View File

@ -0,0 +1,13 @@
struct Foo {
mut:
value int
}
const constant = Foo{ 100 }
fn main() {
mut unused_var := Foo{}
unused_var = Foo{}
mut c := &constant
c.value = 200
}