If I have a struct that encapsulates two members, and updates one based on the other, that's fine as long as I do it this way:
struct A {
value: i64
}
impl A {
pub fn new() -> Self {
A { value: 0 }
}
pub fn do_something(&mut self, other: &B) {
self.value += other.value;
}
pub fn value(&self) -> i64 {
self.value
}
}
struct B {
pub value: i64
}
struct State {
a: A,
b: B
}
impl State {
pub fn new() -> Self {
State {
a: A::new(),
b: B { value: 1 }
}
}
pub fn do_stuff(&mut self) -> i64 {
self.a.do_something(&self.b);
self.a.value()
}
pub fn get_b(&self) -> &B {
&self.b
}
}
fn main() {
let mut state = State::new();
println!("{}", state.do_stuff());
}
That is, when I directly refer to self.b
. But when I change do_stuff()
to this:
pub fn do_stuff(&mut self) -> i64 {
self.a.do_something(self.get_b());
self.a.value()
}
The compiler complains: cannot borrow `*self` as immutable because `self.a` is also borrowed as mutable
.
What if I need to do something more complex than just returning a member in order to get the argument for a.do_something()
? Must I make a function that returns b
by value and store it in a binding, then pass that binding to do_something()
? What if b
is complex?
More importantly to my understanding, what kind of memory-unsafety is the compiler saving me from here?
get_b
toB
had not occured to me, but in this case it works extremely well since the purpose ofState
is to entirely encapsulate bothA
andB
. Many thanks. – Spiritoso