diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 468f04ca4f..e3f251b57a 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -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] diff --git a/vlib/v/checker/tests/array_assign_err.out b/vlib/v/checker/tests/array_assign_err.out index e6a58febd6..f68603df20 100644 --- a/vlib/v/checker/tests/array_assign_err.out +++ b/vlib/v/checker/tests/array_assign_err.out @@ -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 diff --git a/vlib/v/checker/tests/array_of_refs_mutability.out b/vlib/v/checker/tests/array_of_refs_mutability.out new file mode 100644 index 0000000000..85664b4c42 --- /dev/null +++ b/vlib/v/checker/tests/array_of_refs_mutability.out @@ -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 | } diff --git a/vlib/v/checker/tests/array_of_refs_mutability.vv b/vlib/v/checker/tests/array_of_refs_mutability.vv new file mode 100644 index 0000000000..c19fa8d835 --- /dev/null +++ b/vlib/v/checker/tests/array_of_refs_mutability.vv @@ -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 +}