6

This is based on my previous question.

I have code that is failing with borrow checker error and I reduced it as much as I could. This is the result:

struct MyStruct<'a> {
    s: &'a str,
}

impl<'a> MyStruct<'a> {
    fn foo(&'a mut self) {}
}

fn main() {
    let mut m = MyStruct { s: "aaa" };

    m.foo();
    m.foo();
}

It is failing with:

error[E0499]: cannot borrow `m` as mutable more than once at a time
  --> src/main-x.rs:13:5
   |
12 |     m.foo();
   |     - first mutable borrow occurs here
13 |     m.foo();
   |     ^
   |     |
   |     second mutable borrow occurs here
   |     first borrow later used here

The code was reduced so much that it does nothing useful and could be fixed for example by removing the 'a lifetime from the foo function. But I would like to understand why is the code not ok as it is.

My understanding is that MyStruct contains reference to str of some lifetime 'a and foo can be called with self pointing to MyStruct of the same lifetime. I don't see why is m considered mutably borrowed after the first call to foo.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
michalsrb
  • 4,703
  • 1
  • 18
  • 35

1 Answers1

10

When you declare foo as

 fn foo(&'a mut self) {}

you say the mutable borrow of self has the same lifetime 'a as the embedded string. So it stays borrowed as long as the struct lives. Calling foo is like definitely giving away the ownership of the struct.

You can fix it by declaring foo as

 fn foo(&mut self) {}
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Thanks. I guess I understand the compiler's reasoning now, sadly it is not helpful for solving my original issue. I have the reference inside struct inside `PhantomData`. So it is not really held by the struct, I just need to put it there so it can be as a generic argument. But apparently it is all the same to the compiler. I do need the lifetime in `foo`. – michalsrb May 09 '19 at 14:32