diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 82afc32126..f6e27d1956 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -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) diff --git a/vlib/v/checker/tests/assign_const_ptr_int_literal_err.out b/vlib/v/checker/tests/assign_const_ptr_int_literal_err.out index 1454b0797a..72be8ec725 100644 --- a/vlib/v/checker/tests/assign_const_ptr_int_literal_err.out +++ b/vlib/v/checker/tests/assign_const_ptr_int_literal_err.out @@ -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)` \ No newline at end of file + `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 | } diff --git a/vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.out b/vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.out index 85e2184a99..6880f929fa 100644 --- a/vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.out +++ b/vlib/v/checker/tests/assign_immutable_reference_var_with_parenthesis_err.out @@ -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)) diff --git a/vlib/v/checker/tests/const_reference_write_err.out b/vlib/v/checker/tests/const_reference_write_err.out new file mode 100644 index 0000000000..32549da7d4 --- /dev/null +++ b/vlib/v/checker/tests/const_reference_write_err.out @@ -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 | } diff --git a/vlib/v/checker/tests/const_reference_write_err.vv b/vlib/v/checker/tests/const_reference_write_err.vv new file mode 100644 index 0000000000..64613aa71e --- /dev/null +++ b/vlib/v/checker/tests/const_reference_write_err.vv @@ -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}') +} diff --git a/vlib/v/checker/tests/immutable_deref.out b/vlib/v/checker/tests/immutable_deref.out index e69de29bb2..c10c9aaf52 100644 --- a/vlib/v/checker/tests/immutable_deref.out +++ b/vlib/v/checker/tests/immutable_deref.out @@ -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{} diff --git a/vlib/v/checker/tests/immutable_deref.vv b/vlib/v/checker/tests/immutable_deref.vv index 2ac8c26cde..c129bf407c 100644 --- a/vlib/v/checker/tests/immutable_deref.vv +++ b/vlib/v/checker/tests/immutable_deref.vv @@ -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{} diff --git a/vlib/v/checker/tests/mut_assign_ref.out b/vlib/v/checker/tests/mut_assign_ref.out index 412c5737d5..a5e7f87c19 100644 --- a/vlib/v/checker/tests/mut_assign_ref.out +++ b/vlib/v/checker/tests/mut_assign_ref.out @@ -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 | diff --git a/vlib/v/checker/tests/mut_assign_ref.vv b/vlib/v/checker/tests/mut_assign_ref.vv index 4f55435d32..a88d668687 100644 --- a/vlib/v/checker/tests/mut_assign_ref.vv +++ b/vlib/v/checker/tests/mut_assign_ref.vv @@ -15,7 +15,7 @@ fn main() { mut c := &constant c.value = 200 c = &constant - ic := &constant // ok + ic := &constant _ = ic mut mf := f