mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser: fix mutability with chained fields
This commit is contained in:

committed by
Alexander Medvednikov

parent
dae4c4b83f
commit
4f0f99e663
@ -34,6 +34,8 @@ mut:
|
||||
mod string
|
||||
inside_const bool
|
||||
expr_var Var
|
||||
has_immutable_field bool
|
||||
first_immutable_field Var
|
||||
assigned_type string
|
||||
expected_type string
|
||||
tmp_cnt int
|
||||
@ -1405,6 +1407,7 @@ fn (p mut Parser) bterm() string {
|
||||
|
||||
// also called on *, &, @, . (enum)
|
||||
fn (p mut Parser) name_expr() string {
|
||||
p.has_immutable_field = false
|
||||
ph := p.cgen.add_placeholder()
|
||||
// amp
|
||||
ptr := p.tok == .amp
|
||||
@ -1774,17 +1777,24 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
||||
if has_field {
|
||||
struct_field := if typ.name != 'Option' { p.table.var_cgen_name(field_name) } else { field_name }
|
||||
field := p.table.find_field(typ, struct_field)
|
||||
if !field.is_mut && !p.has_immutable_field {
|
||||
p.has_immutable_field = true
|
||||
p.first_immutable_field = field
|
||||
}
|
||||
// Is the next token `=`, `+=` etc? (Are we modifying the field?)
|
||||
next := p.peek()
|
||||
modifying := next.is_assign() || next == .inc || next == .dec
|
||||
modifying := next.is_assign() || next == .inc || next == .dec ||
|
||||
(field.typ.starts_with('array_') && next == .left_shift)
|
||||
is_vi := p.fileis('vid')
|
||||
if !p.builtin_mod && !p.pref.translated && modifying && !field.is_mut && !is_vi {
|
||||
p.error('cannot modify immutable field `$struct_field` (type `$typ.name`)\n' +
|
||||
'declare the field with `mut:`
|
||||
if !p.builtin_mod && !p.pref.translated && modifying && !is_vi
|
||||
&& p.has_immutable_field {
|
||||
f := p.first_immutable_field
|
||||
p.error('cannot modify immutable field `$f.name` (type `$f.parent_fn`)\n' +
|
||||
'declare the field with `mut:`
|
||||
|
||||
struct $typ.name {
|
||||
struct $f.parent_fn {
|
||||
mut:
|
||||
$struct_field $field.typ
|
||||
$f.name $f.typ
|
||||
}
|
||||
')
|
||||
}
|
||||
@ -1796,13 +1806,6 @@ struct $typ.name {
|
||||
// println(field.access_mod)
|
||||
p.error('cannot refer to unexported field `$struct_field` (type `$typ.name`)')
|
||||
}
|
||||
// if field.access_mod ==.public && p.peek() == .assign && !p.builtin_mod && p.mod != typ.mod {
|
||||
// Don't allow `str.len = 0`
|
||||
if field.access_mod == .public && !p.builtin_mod && p.mod != typ.mod {
|
||||
if !field.is_mut && !p.pref.translated && modifying {
|
||||
p.error('cannot modify public immutable field `$struct_field` (type `$typ.name`)')
|
||||
}
|
||||
}
|
||||
p.gen(dot + struct_field)
|
||||
p.next()
|
||||
return field.typ
|
||||
|
Reference in New Issue
Block a user