]>
Commit | Line | Data |
---|---|---|
60c5eb7d XL |
1 | This error occurs when an attempt is made to borrow state past the end of the |
2 | lifetime of a type that implements the `Drop` trait. | |
3 | ||
4 | Erroneous code example: | |
5 | ||
6 | ```compile_fail,E0713 | |
7 | #![feature(nll)] | |
8 | ||
9 | pub struct S<'a> { data: &'a mut String } | |
10 | ||
11 | impl<'a> Drop for S<'a> { | |
12 | fn drop(&mut self) { self.data.push_str("being dropped"); } | |
13 | } | |
14 | ||
15 | fn demo<'a>(s: S<'a>) -> &'a mut String { let p = &mut *s.data; p } | |
16 | ``` | |
17 | ||
18 | Here, `demo` tries to borrow the string data held within its | |
19 | argument `s` and then return that borrow. However, `S` is | |
20 | declared as implementing `Drop`. | |
21 | ||
22 | Structs implementing the `Drop` trait have an implicit destructor that | |
23 | gets called when they go out of scope. This destructor gets exclusive | |
24 | access to the fields of the struct when it runs. | |
25 | ||
26 | This means that when `s` reaches the end of `demo`, its destructor | |
27 | gets exclusive access to its `&mut`-borrowed string data. allowing | |
28 | another borrow of that string data (`p`), to exist across the drop of | |
29 | `s` would be a violation of the principle that `&mut`-borrows have | |
30 | exclusive, unaliased access to their referenced data. | |
31 | ||
32 | This error can be fixed by changing `demo` so that the destructor does | |
33 | not run while the string-data is borrowed; for example by taking `S` | |
34 | by reference: | |
35 | ||
36 | ``` | |
37 | pub struct S<'a> { data: &'a mut String } | |
38 | ||
39 | impl<'a> Drop for S<'a> { | |
40 | fn drop(&mut self) { self.data.push_str("being dropped"); } | |
41 | } | |
42 | ||
43 | fn demo<'a>(s: &'a mut S<'a>) -> &'a mut String { let p = &mut *(*s).data; p } | |
44 | ``` | |
45 | ||
46 | Note that this approach needs a reference to S with lifetime `'a`. | |
47 | Nothing shorter than `'a` will suffice: a shorter lifetime would imply | |
48 | that after `demo` finishes executing, something else (such as the | |
49 | destructor!) could access `s.data` after the end of that shorter | |
50 | lifetime, which would again violate the `&mut`-borrow's exclusive | |
51 | access. |