playground link https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f9217c8f4c6fe708fec852c9515d9fd6
version1()
doesn't work, version2()
does, even though it should be equivalent (simply inlining get_x_mut
)
In my actual code, get_x_mut
is returning a nested field, so it would be quite convenient to have an accessor to abstract out the access.
I'm also confused about why the conflict occurs across loop iterations - I'm not storing any references.
struct Bar<'a> {
foo: Option<&'a Foo<'a>>
}
impl<'a> Bar<'a> {
fn bar(&mut self) {}
}
struct Foo<'a> {
x: Bar<'a>,
y: Option<Bar<'a>>
}
impl<'a> Foo<'a> {
fn get_x_mut(&'a mut self) -> &'a mut Bar {
&mut self.x
}
fn get_y(&self) -> &Option<Bar> {
&self.y
}
fn version1(&'a mut self) {
loop {
if let Some(y) = self.get_y() {
let x = self.get_x_mut();
x.bar();
}
}
}
fn version2(&'a mut self) {
loop {
if let Some(y) = self.get_y() {
let x = &mut self.x;
x.bar();
}
}
}
}
Error message is
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/lib.rs:25:30
|
14 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
...
25 | if let Some(y) = self.get_y() {
| ^^^^^^^^^^^^ immutable borrow occurs here
26 | let x = self.get_x_mut();
| ----------------
| |
| mutable borrow occurs here
| argument requires that `*self` is borrowed for `'a`
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:26:25
|
14 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
...
26 | let x = self.get_x_mut();
| ^^^^^^^^^^^^^^^^
| |
| `*self` was mutably borrowed here in the previous iteration of the loop
| argument requires that `*self` is borrowed for `'a`