mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: do not allow modifying immutable vars via arrays with refs
This commit is contained in:
parent
93b3f1ca55
commit
9cc24c5dac
@ -458,20 +458,42 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
// no point to show the notice, if the old error was already shown:
|
||||
if !old_assign_error_condition {
|
||||
mut_str := if node.op == .decl_assign { 'mut ' } else { '' }
|
||||
c.note('use `${mut_str}array2 ${node.op.str()} array1.clone()` instead of `${mut_str}array2 ${node.op.str()} array1` (or use `unsafe`)',
|
||||
c.warn('use `${mut_str}array2 ${node.op.str()} array1.clone()` instead of `${mut_str}array2 ${node.op.str()} array1` (or use `unsafe`)',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
if left_sym.kind == .array && right_sym.kind == .array && node.op == .assign {
|
||||
// `mut arr := [u8(1),2,3]`
|
||||
// `arr = [byte(4),5,6]`
|
||||
left_info := left_sym.info as ast.Array
|
||||
left_elem_type := c.table.unaliased_type(left_info.elem_type)
|
||||
if left_sym.kind == .array && right_sym.kind == .array {
|
||||
right_info := right_sym.info as ast.Array
|
||||
right_elem_type := c.table.unaliased_type(right_info.elem_type)
|
||||
if left_type_unwrapped.nr_muls() == right_type_unwrapped.nr_muls()
|
||||
&& left_info.nr_dims == right_info.nr_dims && left_elem_type == right_elem_type {
|
||||
continue
|
||||
if node.op in [.decl_assign, .assign] {
|
||||
// Do not allow `mut arr := [&immutable_object]`
|
||||
if mut left is ast.Ident && right_elem_type.is_ptr() {
|
||||
if left.is_mut() || (left.obj is ast.Var && left.obj.is_mut) {
|
||||
if mut right is ast.ArrayInit && right.exprs.len > 0 {
|
||||
elem_expr := right.exprs[0]
|
||||
if elem_expr is ast.PrefixExpr && elem_expr.op == .amp {
|
||||
r := elem_expr.right
|
||||
if r is ast.Ident {
|
||||
obj := r.obj
|
||||
if obj is ast.Var && !obj.is_mut {
|
||||
c.warn('cannot add a referenece to an immutable object to a mutable array',
|
||||
elem_expr.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.op == .assign {
|
||||
// `mut arr := [u8(1),2,3]`
|
||||
// `arr = [byte(4),5,6]`
|
||||
left_info := left_sym.info as ast.Array
|
||||
left_elem_type := c.table.unaliased_type(left_info.elem_type)
|
||||
if left_type_unwrapped.nr_muls() == right_type_unwrapped.nr_muls()
|
||||
&& left_info.nr_dims == right_info.nr_dims && left_elem_type == right_elem_type {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if left_sym.kind == .array_fixed && !c.inside_unsafe && node.op in [.assign, .decl_assign]
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/array_assign_err.vv:8:8: notice: use `mut array2 := array1.clone()` instead of `mut array2 := array1` (or use `unsafe`)
|
||||
vlib/v/checker/tests/array_assign_err.vv:8:8: warning: use `mut array2 := array1.clone()` instead of `mut array2 := array1` (or use `unsafe`)
|
||||
6 | fn main() {
|
||||
7 | a := Dumb{[1, 2, 3]}
|
||||
8 | mut b := a.v // I expect a compiler error
|
||||
|
14
vlib/v/checker/tests/array_of_refs_mutability.out
Normal file
14
vlib/v/checker/tests/array_of_refs_mutability.out
Normal file
@ -0,0 +1,14 @@
|
||||
vlib/v/checker/tests/array_of_refs_mutability.vv:11:14: warning: cannot add a referenece to an immutable object to a mutable array
|
||||
9 | }
|
||||
10 |
|
||||
11 | mut arr := [&x]
|
||||
| ^
|
||||
12 | arr[0].bar = 30
|
||||
13 |
|
||||
vlib/v/checker/tests/array_of_refs_mutability.vv:15:10: warning: cannot add a referenece to an immutable object to a mutable array
|
||||
13 |
|
||||
14 | mut arr2 := [&Foo{}]
|
||||
15 | arr2 = [&x]
|
||||
| ^
|
||||
16 | arr2[0].bar = 40
|
||||
17 | }
|
17
vlib/v/checker/tests/array_of_refs_mutability.vv
Normal file
17
vlib/v/checker/tests/array_of_refs_mutability.vv
Normal file
@ -0,0 +1,17 @@
|
||||
struct Foo {
|
||||
mut:
|
||||
bar int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
x := Foo{
|
||||
bar: 20
|
||||
}
|
||||
|
||||
mut arr := [&x]
|
||||
arr[0].bar = 30
|
||||
|
||||
mut arr2 := [&Foo{}]
|
||||
arr2 = [&x]
|
||||
arr2[0].bar = 40
|
||||
}
|
Loading…
Reference in New Issue
Block a user