checker: fix mutable const bug (fix #14916)

This commit is contained in:
Alexander Medvednikov 2025-06-04 03:48:50 +03:00
parent 03e93b35e3
commit 504d34a0a8
4 changed files with 20 additions and 5 deletions

View File

@ -4,7 +4,7 @@ module checker
import v.ast
// TODO: 600 line function
// TODO: 980 line function
fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
prev_inside_assign := c.inside_assign
c.inside_assign = true

View File

@ -795,6 +795,16 @@ fn (mut c Checker) check_append(mut node ast.InfixExpr, left_type ast.Type, righ
if !left_value_type.has_flag(.option) && right_type.has_flag(.option) {
c.error('unwrapped Option cannot be used in an infix expression', node.pos)
}
right := node.right
if right is ast.PrefixExpr && right.op == .amp {
mut expr2 := right.right
if mut expr2 is ast.Ident {
if !node.left.is_blank_ident() && expr2.obj is ast.ConstField {
c.error('cannot have mutable reference to const `${expr2.name}`', expr2.pos)
}
}
}
if left_value_sym.kind == .interface {
if right_final_sym.kind != .array {
// []Animal << Cat

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/ban_const_ref_mutation.vv:11:14: error: cannot have mutable reference to const `foobar_const`
9 | println('foobar_const.foo: ${foobar_const.foo}') // foobar_const.foo: 123
10 | mut foobars := []&Foobar{}
11 | foobars << &foobar_const
| ~~~~~~~~~~~~
12 | foobars[0].foo = 456
13 | println('foobar_const.foo: ${foobar_const.foo}') // foobar_const.foo: 456

View File

@ -1,4 +1,3 @@
/*
struct Foobar {
mut:
foo int
@ -7,10 +6,9 @@ mut:
const foobar_const = Foobar{123}
fn main() {
println("foobar_const.foo: ${foobar_const.foo}") // foobar_const.foo: 123
println('foobar_const.foo: ${foobar_const.foo}') // foobar_const.foo: 123
mut foobars := []&Foobar{}
foobars << &foobar_const
foobars[0].foo = 456
println("foobar_const.foo: ${foobar_const.foo}") // foobar_const.foo: 456
println('foobar_const.foo: ${foobar_const.foo}') // foobar_const.foo: 456
}
*/