14

I am trying to get a mutable borrow inside a loop, and I cannot get it to work. I've tried all the possible guards, raw pointers, everything.

struct Test<'a> {
    a: &'a str,
}

impl<'a> Test<'a> {
    pub fn new() -> Self {
        Test { a: &mut "test" }
    }

    pub fn dostuff(&'a mut self) {
        self.a = "test";
    }

    pub fn fixme(&'a mut self) {
        let mut i = 0;
        while i < 10 {
            self.dostuff();
            i += 1;
        }
    }
}

fn main() {
    let mut test = Test::new();
    test.fixme();
}
error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/main.rs:19:13
   |
19 |             self.dostuff();
   |             ^^^^ mutable borrow starts here in previous iteration of loop
...
22 |     }
   |     - mutable borrow ends here

Rust Playground example code

I cannot manage to figure how to solve this. I need the fix to still keep the function signatures the same. My code is a lot more complex, but this snippet strips it down to the bare minimum.

Here is the complete code of what I'm trying to solve.

Chronium
  • 906
  • 9
  • 12
  • *I need the fix to still keep the functions the same* — if we cannot change anything, we cannot fix anything. – Shepmaster Sep 24 '17 at 19:25
  • Do you have a good reason to use a `&str` instead of a `String`? If `Test` owns the string, use the owned type. – Boiethios Sep 24 '17 at 19:31
  • I've added the actual code I'm having trouble with. Pushed it to a git repo. The playground gist was just an example of the error itself. – Chronium Sep 24 '17 at 19:48

1 Answers1

16

When you write fn dostuff(&'a mut self) you are enforcing that the reference to self must live at least as long as the lifetime 'a. But it's the same 'a as you have used in the definition of the Test struct. This means that callers of dostuff have to lend self for the entire lifetime of test. After dostuff() has been called once, self is now borrowed and the borrow doesn't finish until test is dropped. By definition, you can only call that function once, so you cannot call it in a loop.

I need the fix to still keep the function signatures the same

So, you should now understand that this is an impossible requirement. You can have either the function signature as it is, or you can call it in a loop. You can't have both.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • 2
    I have a similar problem, but I don't have the strict function signature requirement like the OP: what are my options? – CrepeGoat Feb 09 '22 at 20:33
  • You can add a DIFFERENT lifetime to the function doStuff(). This way the compiler knows that the mutable reference to self will only need to live for the duration of the function call. ``` pub fn dostuff<'b>(&'b mut self) { self.a = "test"; } ``` – Thore Jul 19 '23 at 09:13