1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: disallow mut_ptr = &immutable_var (#13814)

This commit is contained in:
Nick Treleaven 2022-03-24 18:43:25 +00:00 committed by GitHub
parent 9bbb52e9cc
commit a4ab3c1f14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 77 additions and 39 deletions

View File

@ -794,7 +794,21 @@ pub mut:
name string
kind IdentKind
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 {

View File

@ -559,15 +559,10 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if right_node.right.obj is ast.Var {
v := right_node.right.obj
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',
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)
}
}
if !c.inside_unsafe && assigned_var.is_mut() && !right_node.right.is_mut() {
c.error('`$right_node.right.name` is immutable, cannot have a mutable reference to it',
right_node.pos)
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ fn test_voidptr_casted_as_an_interface_reference() {
dump(pi)
assert f(pi) == '&IAbc(0x0)'
//
i := IAbc(Abc{})
mut i := IAbc(Abc{})
pi = &i
dump(pi)
assert f(pi).contains('x: 123')

View File

@ -1,7 +1,11 @@
fn test_reference_array_init() {
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
}
println(b)