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:
|
// no point to show the notice, if the old error was already shown:
|
||||||
if !old_assign_error_condition {
|
if !old_assign_error_condition {
|
||||||
mut_str := if node.op == .decl_assign { 'mut ' } else { '' }
|
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)
|
node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left_sym.kind == .array && right_sym.kind == .array && node.op == .assign {
|
if left_sym.kind == .array && right_sym.kind == .array {
|
||||||
// `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)
|
|
||||||
right_info := right_sym.info as ast.Array
|
right_info := right_sym.info as ast.Array
|
||||||
right_elem_type := c.table.unaliased_type(right_info.elem_type)
|
right_elem_type := c.table.unaliased_type(right_info.elem_type)
|
||||||
if left_type_unwrapped.nr_muls() == right_type_unwrapped.nr_muls()
|
if node.op in [.decl_assign, .assign] {
|
||||||
&& left_info.nr_dims == right_info.nr_dims && left_elem_type == right_elem_type {
|
// Do not allow `mut arr := [&immutable_object]`
|
||||||
continue
|
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]
|
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() {
|
6 | fn main() {
|
||||||
7 | a := Dumb{[1, 2, 3]}
|
7 | a := Dumb{[1, 2, 3]}
|
||||||
8 | mut b := a.v // I expect a compiler error
|
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