| This error occurs when an attempt is made to borrow state past the end of the | |
| lifetime of a type that implements the `Drop` trait. | |
| Erroneous code example: | |
| ```compile_fail,E0713 | |
| pub struct S<'a> { data: &'a mut String } | |
| impl<'a> Drop for S<'a> { | |
| fn drop(&mut self) { self.data.push_str("being dropped"); } | |
| } | |
| fn demo<'a>(s: S<'a>) -> &'a mut String { let p = &mut *s.data; p } | |
| ``` | |
| Here, `demo` tries to borrow the string data held within its | |
| argument `s` and then return that borrow. However, `S` is | |
| declared as implementing `Drop`. | |
| Structs implementing the `Drop` trait have an implicit destructor that | |
| gets called when they go out of scope. This destructor gets exclusive | |
| access to the fields of the struct when it runs. | |
| This means that when `s` reaches the end of `demo`, its destructor | |
| gets exclusive access to its `&mut`-borrowed string data. allowing | |
| another borrow of that string data (`p`), to exist across the drop of | |
| `s` would be a violation of the principle that `&mut`-borrows have | |
| exclusive, unaliased access to their referenced data. | |
| This error can be fixed by changing `demo` so that the destructor does | |
| not run while the string-data is borrowed; for example by taking `S` | |
| by reference: | |
| ``` | |
| pub struct S<'a> { data: &'a mut String } | |
| impl<'a> Drop for S<'a> { | |
| fn drop(&mut self) { self.data.push_str("being dropped"); } | |
| } | |
| fn demo<'a>(s: &'a mut S<'a>) -> &'a mut String { let p = &mut *(*s).data; p } | |
| ``` | |
| Note that this approach needs a reference to S with lifetime `'a`. | |
| Nothing shorter than `'a` will suffice: a shorter lifetime would imply | |
| that after `demo` finishes executing, something else (such as the | |
| destructor!) could access `s.data` after the end of that shorter | |
| lifetime, which would again violate the `&mut`-borrow's exclusive | |
| access. |