E4094

E4094#

Cannot modify a read-only field.

For a read-only struct, you cannot modify the value of a field using assignment outside of the package where the type is defined.

错误示例#

Suppose you have a package a in module username/hello:

a/moon.pkg.json:

{}

a/a.mbt:

pub struct T {
  mut value : Int
}

pub fn T::new() -> T {
  T::{ value: 0 }
}

pub fn T::set(self : T, value : Int) -> Unit {
  self.value = value
}

And you have another package b in the same module:

b/moon.pkg.json:

{
  "is-main": true,
  "import": [
    "username/hello/a"
  ]
}

b/b.mbt:

fn main {
  let a = @a.T::new()
  a.value = 3 // Error: Cannot modify a read-only field: value
}

建议#

If you have control over the package where the type is defined, you can simply make the struct has pub(all) visibility.

`a/a.mbt

pub(all) struct T {
  mut value : Int
}

However, this might not be the best solution if you want to hide the implementation details of the struct or protect the invariant of the struct. We recommend using getter/setter pattern to guard the access to the struct fields.

b/b.mbt:

fn main {
  let a = @a.T::new()
  a.set(3)
}