checker: disallow `mut_ptr = &immutable_var` (#13814)
parent
9bbb52e9cc
commit
a4ab3c1f14
|
@ -794,7 +794,21 @@ pub mut:
|
||||||
name string
|
name string
|
||||||
kind IdentKind
|
kind IdentKind
|
||||||
info IdentInfo
|
info IdentInfo
|
||||||
is_mut bool
|
is_mut bool // if mut *token* is before name. Use `is_mut()` to lookup mut variable
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (i &Ident) is_mut() bool {
|
||||||
|
match i.obj {
|
||||||
|
Var {
|
||||||
|
return i.obj.is_mut
|
||||||
|
}
|
||||||
|
ConstField {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
AsmRegister, GlobalField {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (i &Ident) var_info() IdentVar {
|
pub fn (i &Ident) var_info() IdentVar {
|
||||||
|
|
|
@ -559,15 +559,10 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||||
if right_node.right.obj is ast.Var {
|
if right_node.right.obj is ast.Var {
|
||||||
v := right_node.right.obj
|
v := right_node.right.obj
|
||||||
right_type0 = v.typ
|
right_type0 = v.typ
|
||||||
if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe {
|
}
|
||||||
c.error('`$right_node.right.name` is immutable, cannot have a mutable reference to it',
|
if !c.inside_unsafe && assigned_var.is_mut() && !right_node.right.is_mut() {
|
||||||
right_node.pos)
|
c.error('`$right_node.right.name` is immutable, cannot have a mutable reference to it',
|
||||||
}
|
right_node.pos)
|
||||||
} else if right_node.right.obj is ast.ConstField {
|
|
||||||
if assigned_var.is_mut && !c.inside_unsafe {
|
|
||||||
c.error('`$right_node.right.name` is immutable, cannot have a mutable reference to it',
|
|
||||||
right_node.pos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
vlib/v/checker/tests/modify_const_with_ref.vv:11:11: 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 | }
|
|
||||||
vlib/v/checker/tests/modify_const_with_ref.vv:9:6: error: unused variable: `unused_var`
|
|
||||||
7 |
|
|
||||||
8 | fn main() {
|
|
||||||
9 | mut unused_var := Foo{}
|
|
||||||
| ~~~~~~~~~~
|
|
||||||
10 | unused_var = Foo{}
|
|
||||||
11 | mut c := &constant
|
|
|
@ -1,13 +0,0 @@
|
||||||
struct Foo {
|
|
||||||
mut:
|
|
||||||
value int
|
|
||||||
}
|
|
||||||
|
|
||||||
const constant = Foo{ 100 }
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
mut unused_var := Foo{}
|
|
||||||
unused_var = Foo{}
|
|
||||||
mut c := &constant
|
|
||||||
c.value = 200
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
vlib/v/checker/tests/mut_assign_ref.vv:10:12: error: `f` is immutable, cannot have a mutable reference to it
|
||||||
|
8 | fn main() {
|
||||||
|
9 | f := Foo{}
|
||||||
|
10 | mut pf := &f
|
||||||
|
| ^
|
||||||
|
11 | pf = &f
|
||||||
|
12 | p := &f
|
||||||
|
vlib/v/checker/tests/mut_assign_ref.vv:11:7: error: `f` is immutable, cannot have a mutable reference to it
|
||||||
|
9 | f := Foo{}
|
||||||
|
10 | mut pf := &f
|
||||||
|
11 | pf = &f
|
||||||
|
| ^
|
||||||
|
12 | p := &f
|
||||||
|
13 | _ = p
|
||||||
|
vlib/v/checker/tests/mut_assign_ref.vv:15:11: error: `constant` is immutable, cannot have a mutable reference to it
|
||||||
|
13 | _ = p
|
||||||
|
14 |
|
||||||
|
15 | mut c := &constant
|
||||||
|
| ^
|
||||||
|
16 | c.value = 200
|
||||||
|
17 | c = &constant
|
||||||
|
vlib/v/checker/tests/mut_assign_ref.vv:17:6: error: `constant` is immutable, cannot have a mutable reference to it
|
||||||
|
15 | mut c := &constant
|
||||||
|
16 | c.value = 200
|
||||||
|
17 | c = &constant
|
||||||
|
| ^
|
||||||
|
18 | ic := &constant // ok
|
||||||
|
19 | _=ic
|
|
@ -0,0 +1,24 @@
|
||||||
|
struct Foo {
|
||||||
|
mut:
|
||||||
|
value int
|
||||||
|
}
|
||||||
|
|
||||||
|
const constant = Foo{ 100 }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f := Foo{}
|
||||||
|
mut pf := &f
|
||||||
|
pf = &f
|
||||||
|
p := &f
|
||||||
|
_ = p
|
||||||
|
|
||||||
|
mut c := &constant
|
||||||
|
c.value = 200
|
||||||
|
c = &constant
|
||||||
|
ic := &constant // ok
|
||||||
|
_=ic
|
||||||
|
|
||||||
|
mut mf := f
|
||||||
|
pf = &mf // ok
|
||||||
|
_ = pf
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ fn test_voidptr_casted_as_an_interface_reference() {
|
||||||
dump(pi)
|
dump(pi)
|
||||||
assert f(pi) == '&IAbc(0x0)'
|
assert f(pi) == '&IAbc(0x0)'
|
||||||
//
|
//
|
||||||
i := IAbc(Abc{})
|
mut i := IAbc(Abc{})
|
||||||
pi = &i
|
pi = &i
|
||||||
dump(pi)
|
dump(pi)
|
||||||
assert f(pi).contains('x: 123')
|
assert f(pi).contains('x: 123')
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
fn test_reference_array_init() {
|
fn test_reference_array_init() {
|
||||||
mut b := &[5, 6, 7]
|
mut b := &[5, 6, 7]
|
||||||
{
|
{
|
||||||
a := [1, 2, 3]
|
mut a := [1, 2, 3]
|
||||||
|
// TODO: this should probably produce a notice at least,
|
||||||
|
// (without unsafe{&a}), since it takes the address of something
|
||||||
|
// on the stack, that will very soon be out of scope, even
|
||||||
|
// though it is still in the same function:
|
||||||
b = &a
|
b = &a
|
||||||
}
|
}
|
||||||
println(b)
|
println(b)
|
||||||
|
|
Loading…
Reference in New Issue