1

I'm trying to make a struct that holds an mutable reference. Accessing the mutable reference multiple times through its field works fine. However, if I use a getter instead, it does not compile.

struct IntBorrower<'inner>(&'inner mut i32);

impl<'outer: 'inner, 'inner> IntBorrower<'inner> {
    fn int_mut(&'outer mut self) -> &'inner mut i32 {
        &mut self.0
    }

    //this compiles
    fn do_something(&'outer mut self) {
        {
            *self.0 += 5;
        }

        {
            *self.0 += 5;
        }
    }

    //this does not compile
    fn do_something_but_with_getters(&'outer mut self) {
        {
            *self.int_mut() += 5;
        }

        {
            *self.int_mut() += 5;
        }
    }
}

fn main() {}

I get this error:

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/main.rs:26:14
   |
22 |             *self.int_mut() += 5;
   |              ---- first mutable borrow occurs here
...
26 |             *self.int_mut() += 5;
   |              ^^^^ second mutable borrow occurs here
27 |         }
28 |     }
   |     - first borrow ends here

Shouldn't the first mutable borrow end inside those brackets just like in the previous function? Why does this happen?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Maple
  • 41
  • 3
  • 1
    https://stackoverflow.com/questions/31067031/cannot-borrow-as-mutable-more-than-once-at-a-time-in-one-code-but-can-in-anoth could be a duplicate. Do you want to understand why the two things are different or do you just want to know how to fix it? – trent Dec 21 '17 at 22:45
  • 1
    I'm always trying to root out the cause of this mistake; *why* do you have so many lifetimes defined in your code? What learning route suggested that doing that was a good idea? – Shepmaster Dec 21 '17 at 22:47
  • I'm more interested in an explanation as I already found a workaround. Although a fix would be fine. – Maple Dec 21 '17 at 22:48
  • 1
    (Also https://stackoverflow.com/questions/24847533/why-does-rust-borrow-checker-reject-this-code/24861538#24861538 and https://stackoverflow.com/questions/39827244/who-borrowed-a-variable ...) – trent Dec 21 '17 at 22:49
  • I dont think those three links are much related since they all involve immutable references. Changing the reference in my code snippet to an immutable reference and removing the "+= 5" compiles fine. – Maple Dec 21 '17 at 23:02
  • 1
    @Maple My question is: why did you define `outer` at all? What blog post, book, documentation etc. suggested that was a good idea to start with? – Shepmaster Dec 21 '17 at 23:15
  • In fact I think this definitely is a duplicate of one of the ones I linked -- `'outer` and `'inner` just make it look funny. The error is the same if you use `'inner` everywhere, and for the same reason. The answer is the same, too: [*delete all the lifetimes*](https://play.rust-lang.org/?gist=9bbaecdc211bafdcf5bc77981d218a8b&version=stable). – trent Dec 21 '17 at 23:15
  • I'm using two lifetimes. 'outer for self and 'inner for the mutable reference. I think https://stackoverflow.com/a/39828602/8022804 explains why they should be separate. I accidentally deleted the previous comment you replied to, sorry about that. – Maple Dec 21 '17 at 23:16
  • `&mut self` is the problem here, not the mutability of the internal reference (necessarily). – trent Dec 21 '17 at 23:24
  • @trentcl your link to the rust playground helped clarify things more. Thanks. – Maple Dec 21 '17 at 23:31

0 Answers0