0

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`
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
ajp
  • 1,723
  • 14
  • 22
  • People again are trying to make self-referential structs. Don't do it. See [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) – Chayim Friedman Aug 10 '23 at 23:52

1 Answers1

0

Because you've specified the lifetimes wrong.

This:

fn get_x_mut(&'a mut self) -> &'a mut Bar {
    &mut self.x
}

Should be this:

fn get_x_mut(&mut self) -> &mut Bar<'a> {
    &mut self.x
}

Which is equivalent to this:

fn get_x_mut<'b>(&'b mut self) -> &'b mut Bar<'a> {
    &mut self.x
}

However, the whole thing is wrong to begin with. You're trying to create a self-referential struct, which is simply not allowed in Rust. You might have succeeded for now, but eventually you will fail. See Why can't I store a value and a reference to that value in the same struct?.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77