checker: disallow references to constants (fix #23935) (#23942)

This commit is contained in:
Felipe Pena 2025-03-16 08:03:12 -03:00 committed by GitHub
parent 725e25991d
commit e995d991f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 101 additions and 4 deletions

View file

@ -899,6 +899,7 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
// Check `x := &y` and `mut x := <-ch`
if mut right_first is ast.PrefixExpr {
mut right_node := right_first
is_amp := right_first.op == .amp
left_first := node.left[0]
if left_first is ast.Ident {
assigned_var := left_first
@ -920,6 +921,10 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
v := expr.obj
right_first_type = v.typ
}
if is_amp && !node.left[0].is_blank_ident() && expr.obj is ast.ConstField {
c.error('cannot have mutable reference to const `${expr.name}`',
right_node.pos)
}
if !c.inside_unsafe && assigned_var.is_mut() && !expr.is_mut() {
c.error('`${expr.name}` is immutable, cannot have a mutable reference to it',
right_node.pos)

View file

@ -6,4 +6,11 @@ vlib/v/checker/tests/assign_const_ptr_int_literal_err.vv:4:8: error: cannot assi
5 | dump(b)
6 | }
Details: Specify the type for the constant value. Example:
`const a = int(3)`
`const a = int(3)`
vlib/v/checker/tests/assign_const_ptr_int_literal_err.vv:4:7: error: cannot have mutable reference to const `a`
2 |
3 | fn main() {
4 | b := &a
| ^
5 | dump(b)
6 | }

View file

@ -12,6 +12,13 @@ vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:12:1
| ~~~~~~~~~~~~~~
13 | println(a)
14 | println(b)
vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:10:11: error: cannot have mutable reference to const `a_char`
8 |
9 | fn foo() {
10 | mut a := &(a_char)
| ^
11 | mut b := &((a_char))
12 | mut c := &((((a_char))))
vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:10:11: error: `a_char` is immutable, cannot have a mutable reference to it
8 |
9 | fn foo() {
@ -19,6 +26,13 @@ vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:10:1
| ^
11 | mut b := &((a_char))
12 | mut c := &((((a_char))))
vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:11:11: error: cannot have mutable reference to const `a_char`
9 | fn foo() {
10 | mut a := &(a_char)
11 | mut b := &((a_char))
| ^
12 | mut c := &((((a_char))))
13 | println(a)
vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:11:11: error: `a_char` is immutable, cannot have a mutable reference to it
9 | fn foo() {
10 | mut a := &(a_char)
@ -26,6 +40,13 @@ vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:11:1
| ^
12 | mut c := &((((a_char))))
13 | println(a)
vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:12:11: error: cannot have mutable reference to const `a_char`
10 | mut a := &(a_char)
11 | mut b := &((a_char))
12 | mut c := &((((a_char))))
| ^
13 | println(a)
14 | println(b)
vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.vv:12:11: error: `a_char` is immutable, cannot have a mutable reference to it
10 | mut a := &(a_char)
11 | mut b := &((a_char))

View file

@ -0,0 +1,14 @@
vlib/v/checker/tests/const_reference_write_err.vv:14:10: error: cannot have mutable reference to const `a_string`
12 | }
13 | unsafe {
14 | ptr := &a_string
| ^
15 | *ptr = f
16 |
vlib/v/checker/tests/const_reference_write_err.vv:17:11: error: cannot have mutable reference to const `a_struct`
15 | *ptr = f
16 |
17 | ptr2 := &a_struct
| ^
18 | *ptr2 = a
19 | }

View file

@ -0,0 +1,23 @@
const a_string = ''
const a_struct = A1{}
struct A1 {
a_string string
}
fn main() {
f := '123'
a := A1{
a_string: f
}
unsafe {
ptr := &a_string
*ptr = f
ptr2 := &a_struct
*ptr2 = a
}
println('f: ${f} vs. a_string: ${a_string} vs. a_struct.a_string: ${a_struct.a_string}')
println('f == a_string : ${a_string == f}')
println('f == a_struct.a_string : ${a_struct.a_string == f}')
}

View file

@ -0,0 +1,7 @@
vlib/v/checker/tests/immutable_deref.vv:6:7: error: cannot have mutable reference to const `ctx_ptr`
4 |
5 | fn main() {
6 | x := &ctx_ptr
| ^
7 | unsafe {
8 | *x = &Context{}

View file

@ -3,7 +3,6 @@ struct Context {}
const ctx_ptr = &Context(unsafe { nil })
fn main() {
// TODO: unsafe bug, having this declaration inside `unsafe` results in an error
x := &ctx_ptr
unsafe {
*x = &Context{}

View file

@ -12,6 +12,13 @@ vlib/v/checker/tests/mut_assign_ref.vv:11:7: error: `f` is immutable, cannot hav
| ^
12 | p := &f
13 | _ = p
vlib/v/checker/tests/mut_assign_ref.vv:15:11: error: cannot have mutable reference to const `constant`
13 | _ = p
14 |
15 | mut c := &constant
| ^
16 | c.value = 200
17 | c = &constant
vlib/v/checker/tests/mut_assign_ref.vv:15:11: error: `constant` is immutable, cannot have a mutable reference to it
13 | _ = p
14 |
@ -19,10 +26,24 @@ vlib/v/checker/tests/mut_assign_ref.vv:15:11: error: `constant` is immutable, ca
| ^
16 | c.value = 200
17 | c = &constant
vlib/v/checker/tests/mut_assign_ref.vv:17:6: error: cannot have mutable reference to const `constant`
15 | mut c := &constant
16 | c.value = 200
17 | c = &constant
| ^
18 | ic := &constant
19 | _ = ic
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
18 | ic := &constant
19 | _ = ic
vlib/v/checker/tests/mut_assign_ref.vv:18:8: error: cannot have mutable reference to const `constant`
16 | c.value = 200
17 | c = &constant
18 | ic := &constant
| ^
19 | _ = ic
20 |

View file

@ -15,7 +15,7 @@ fn main() {
mut c := &constant
c.value = 200
c = &constant
ic := &constant // ok
ic := &constant
_ = ic
mut mf := f