@@ -21,14 +21,35 @@ where
21
21
}
22
22
```
23
23
24
- In this example we have a trait that borrows some inner data element of type ` V `
25
- from an outer type ` T ` , through an intermediate type ` U ` . The compiler is unable
26
- to prove that the livetime of ` U ` is long enough to support the reference. To
27
- fix the issue we can explicitly add lifetime specifiers to the ` NestedBorrowMut `
28
- trait, which link the lifetimes of the various data types and allow the code to
29
- compile.
30
-
31
- Working implementation of the ` NestedBorrowMut ` trait:
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 ` .
38
+
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 ` .
47
+
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.
32
53
33
54
```
34
55
use std::borrow::BorrowMut;
0 commit comments