How can I force a struct's field to always be

2020-02-28 03:26发布

In Rust, you don't specify mutability inside a struct, but it is inherited from the variable binding. That's great, but is it possible to force a field to be always immutable, even when the root is mutable?

Something like this hypothetical syntax:

struct A {
    immut s: Shape, // immutable by design
    bla: Bla, // this field inheriting (im)mutability
}
let mut a = make_a();
a.s = x/*...*/; // illegal

This would help to maintain nice semantic restrictions in a program, just like Java's final does (in a very limited way).

Also, we could imagine this kind of struct having some non-owning references to internal immutable data, taking advantage of this immutability...

3条回答
Fickle 薄情
2楼-- · 2020-02-28 03:45

A Solution could be to have a more general approach:

pub struct Immutable<T> {
    value : T ,
}

impl<T> Immutable<T> {

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

    pub fn get( &self) -> &T { &self.value }
}

Now it is possible to use the Immutable struct in every case for every other type.

Given this into a module avoids changing the content of the Immutable object. It is still possible to change the variable which holds the Immutable object itself by overwriting it by a new Object but you should notice it by the Immutable::new statement and so you can avoid using it.

查看更多
姐就是有狂的资本
3楼-- · 2020-02-28 03:53

It's impossible to have immutability of a single field. That was an option in an ancient version of Rust (think before 0.8), but it was dropped because the rules confused a LOT of people. How was it confusing, you might ask? Think about it like this: if a field is declared mutable and struct is declared mutable and the reference used was an immutable reference (&) then the field is _______.

The best, as Lily Ballard noted, is that you can declare your Shape field as private and make a getter method using impl A {...}.

mod inner {
    pub struct A {
        s: i32, // can't be seen outside of module
        pub bla: i32,
    }

    impl A {
        pub fn new() -> Self {
            Self { s: 0, bla: 42 }
        }

        pub fn get_s(&self) -> i32 {
            self.s
        }
    }
}
let mut a = inner::A::new();
a.s = 42; // illegal
println!("{}", a.s); // also illegal
println!("{}", a.get_s()); // could be made to serve as a read-only method
error[E0616]: field `s` of struct `main::inner::A` is private
  --> src/main.rs:20:5
   |
20 |     a.s = 42; // illegal
   |     ^^^

error[E0616]: field `s` of struct `main::inner::A` is private
  --> src/main.rs:21:20
   |
21 |     println!("{}", a.s); // also illegal
   |                    ^^^

There is proposition that might drop notions of mutability and immutability completely (you can't say a struct never changes). See Niko's explanation for that change.

查看更多
迷人小祖宗
4楼-- · 2020-02-28 03:54

You can't force immutability on a field. How would the struct mutate its own value when necessary?

What you can do is make the field private and expose a getter method to return a reference to it (or to copy/clone the value).

查看更多
登录 后发表回答