1
- This error occurs when there is insufficient information for the rust compiler
2
- to prove that a type has a long enough lifetime .
1
+ This error occurs when there is an unsatisfied outlives bound on a generic
2
+ type parameter or associated type .
3
3
4
4
Erroneous code example:
5
5
@@ -13,58 +13,63 @@ trait NestedBorrowMut<U, V> {
13
13
impl<T, U, V> NestedBorrowMut<U, V> for T
14
14
where
15
15
T: BorrowMut<U>,
16
- U: BorrowMut<V>, // error: missing lifetime specifier
16
+ U: BorrowMut<V>,
17
17
{
18
18
fn nested_borrow_mut(&mut self) -> &mut V {
19
- self.borrow_mut().borrow_mut()
19
+ let u_ref = self.borrow_mut();
20
+ let v_ref = u_ref.borrow_mut();
21
+ v_ref
20
22
}
21
23
}
22
24
```
23
25
24
- Why doesn't this code compile? The problem has to do with Rust's rules for
25
- lifetime elision in functions (Chapter 10.3 in the Rust book). One of the
26
- inputs is a reference to ` self ` , so the compiler attempts to assign the
27
- the same lifetime to the ` &mut self ` input and ` &mut V ` output to the
28
- ` nested_borrow_mut() ` function. The problem is that there is no way for the
29
- compiler to directly figure out how these two lifetimes are related in the
30
- implementation of the function. We're implementing the ` NextedBorrowMut `
31
- trait for a type ` T ` , so the ` &mut self ` reference has the lifetime of ` T ` .
32
- We know that ` T ` implements the ` BorrowMut ` trait returning a reference to ` U ` ,
33
- and that ` U ` implements the ` BorrowMut ` trait returning a reference to ` V ` .
34
- The key is that we have not told the compiler that those two ` U ` lifetimes
35
- are the same: for all it knows, we could be that the first ` BorrowMut ` trait
36
- on ` T ` works with a lifetime ` 'a ` and the second ` BorrowMut ` trait on ` U `
37
- works on a lifetime ` 'b ` .
26
+ Why doesn't this code compile? It helps to look at the lifetime bounds that
27
+ the compiler is automatically adding ("Lifetime Ellision", Chapter 10.3 in the
28
+ Rust book) to the ` nested_borrow_mut ` and ` borrow_mut ` functions. In both cases
29
+ the input is a reference to ` self ` , so the compiler attempts to assign the
30
+ the same lifetime to the input and output.
38
31
39
- The fix here is to add explicit lifetime annotations that tell the compiler
40
- that the lifetime of the output is in fact the same as the lifetime of the
41
- input (` self ` ). There are three references involved, to objects of type ` T `
42
- (` self ` ), ` U ` (the intermediate type), and ` V ` (the return type). In the
43
- working code below, we see that all have been given the same lifetime ` 'a ` :
44
- - ` &'a mut self ` in the function argument list for ` T `
45
- - ` U: BorrowMut<V> + 'a ` in the trait bounds for ` U `
46
- - ` &'a mut V ` in the function return for ` V ` .
32
+ Looking specifically at ` nested_borrow_mut ` ,
33
+ we see that there are three object references to keep track of,
34
+ along with their associated lifetimes:
35
+ - ` self ` (which is a ` &mut T ` )
36
+ - ` u_ref ` (which is a ` &mut U ` )
37
+ - ` v_ref ` (which is a ` &mut V ` )
47
38
48
- The compiler can the check that the implementation of the
49
- ` nested_borrow_mut() ` function satisfies these lifetimes. There are two
50
- functions being called inside of ` nested_borrow_mut() ` , both of which are
51
- the ` borrow_mut() ` function, which promises that the output lifetime is
52
- the same as the input lifetime (see lifetime elision rules), which checks out.
39
+ The ` borrow_mut() ` method implicitly requires that that the input and output
40
+ have the same lifetime bounds. Thus:
53
41
42
+ ``` rust
43
+ let u_ref = self . borrow_mut ();
44
+ let v_ref = u_ref . borrow_mut ();
54
45
```
46
+
47
+ Imply that ` u_ref ` and ` self ` must share a lifetime bound, and also that
48
+ ` v_ref ` and ` u_ref ` share a lifetime bound. The problem is that the function
49
+ signature for ` nested_borrow_mut ` only gives the compiler information about the
50
+ lifetimes of ` self ` and ` v_ref ` -- nothing about ` u_ref ` .
51
+
52
+ The way to fix this error is then to explicitly tell the compiler that the
53
+ lifetime of ` u_ref ` is the same as ` self ` and ` v_ref ` , which then allows it
54
+ to satisfy the two lifetime bound requirements described above.
55
+
56
+ Here is the working version of the code:
57
+ ``` rust
55
58
use std :: borrow :: BorrowMut ;
56
59
57
60
trait NestedBorrowMut <'a , U , V > {
58
- fn nested_borrow_mut(& 'a mut self) -> &'a mut V;
61
+ fn nested_borrow_mut (& 'a mut self ) -> & 'a mut V ;
59
62
}
60
63
61
64
impl <'a , T , U , V > NestedBorrowMut <'a , U , V > for T
62
65
where
63
66
T : BorrowMut <U >,
64
- U: BorrowMut<V> + 'a, // Adding lifetime specifier
67
+ U : BorrowMut <V > + 'a ,
65
68
{
66
69
fn nested_borrow_mut (& 'a mut self ) -> & 'a mut V {
67
- self.borrow_mut().borrow_mut()
70
+ let u_ref = self . borrow_mut ();
71
+ let v_ref = u_ref . borrow_mut ();
72
+ v_ref
68
73
}
69
74
}
70
75
```
0 commit comments