I have a type (A) that contains another type (B). I have (A) return a mutable reference to (B) so we can update it nicely:
struct A {
b: B,
}
struct B {
value: u32,
}
impl A {
fn new() -> Self {
Self {
b: B::new(),
}
}
fn b(&mut self) -> &mut B {
&mut self.b
}
}
impl B {
fn new() -> Self {
Self {
value: 5,
}
}
fn value(&self) -> u32 {
self.value
}
fn update(&mut self, new_value: u32) {
self.value = new_value;
}
}
fn main() {
let mut a = A::new();
println!("value is: {}", a.b().value());
a.b().update(10);
println!("value is: {}", a.b().value());
}
This works just fine:
value is: 5
value is: 10
But now I want to implement the Display trait for (A):
impl fmt::Display for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.b().value())
}
}
When adding this code, I get the following error:
error[E0596]: cannot borrow `*self` as mutable, as it is behind a `&` reference
--> src\main.rs:49:25
|
49 | write!(f, "{}", self.b().value())
|
I understand what the error is telling me. But I'm not sure the best idiomatic way to fix it.
I got it to work by making separate functions in impl A, where B can be returned as either mutable or immutable:
impl A {
fn new() -> Self {
Self {
b: B::new(),
}
}
fn b(&self) -> &B {
&self.b
}
fn b_mut(&mut self) -> &mut B {
&mut self.b
}
}
But this seems a little sloppy to me. I figure there are three possibilities:
(1) My initial approach is not idiomatic, and there's a more appropriate way to accomplish this
(2) There's actually an easy fix with just a few keystrokes, that I haven't been able to find in my searches
(3) This is just the way it is
Any advice on this situation would be most helpful.