Improve E0311.md description
This commit is contained in:
parent
a9cefd0441
commit
dbcc409556
@ -21,14 +21,35 @@ where
|
||||
}
|
||||
```
|
||||
|
||||
In this example we have a trait that borrows some inner data element of type `V`
|
||||
from an outer type `T`, through an intermediate type `U`. The compiler is unable
|
||||
to prove that the livetime of `U` is long enough to support the reference. To
|
||||
fix the issue we can explicitly add lifetime specifiers to the `NestedBorrowMut`
|
||||
trait, which link the lifetimes of the various data types and allow the code to
|
||||
compile.
|
||||
Why doesn't this code compile? The problem has to do with Rust's rules for
|
||||
lifetime elision in functions (Chapter 10.3 in the Rust book). One of the
|
||||
inputs is a reference to `self`, so the compiler attempts to assign the
|
||||
the same lifetime to the `&mut self` input and `&mut V` output to the
|
||||
`nested_borrow_mut()` function. The problem is that there is no way for the
|
||||
compiler to directly figure out how these two lifetimes are related in the
|
||||
implementation of the function. We're implementing the `NextedBorrowMut`
|
||||
trait for a type `T`, so the `&mut self` reference has the lifetime of `T`.
|
||||
We know that `T` implements the `BorrowMut` trait returning a reference to `U`,
|
||||
and that `U` implements the `BorrowMut` trait returning a reference to `V`.
|
||||
The key is that we have not told the compiler that those two `U` lifetimes
|
||||
are the same: for all it knows, we could be that the first `BorrowMut` trait
|
||||
on `T` works with a lifetime `'a` and the second `BorrowMut` trait on `U`
|
||||
works on a lifetime `'b`.
|
||||
|
||||
Working implementation of the `NestedBorrowMut` trait:
|
||||
The fix here is to add explicit lifetime annotations that tell the compiler
|
||||
that the lifetime of the output is in fact the same as the lifetime of the
|
||||
input (`self`). There are three references involved, to objects of type `T`
|
||||
(`self`), `U` (the intermediate type), and `V` (the return type). In the
|
||||
working code below, we see that all have been given the same lifetime `'a`:
|
||||
- `&'a mut self` in the function argument list for `T`
|
||||
- `U: BorrowMut<V> + 'a` in the trait bounds for `U`
|
||||
- `&'a mut V` in the function return for `V`.
|
||||
|
||||
The compiler can the check that the implementation of the
|
||||
`nested_borrow_mut()` function satisfies these lifetimes. There are two
|
||||
functions being called inside of `nested_borrow_mut()`, both of which are
|
||||
the `borrow_mut()` function, which promises that the output lifetime is
|
||||
the same as the input lifetime (see lifetime elision rules), which checks out.
|
||||
|
||||
```
|
||||
use std::borrow::BorrowMut;
|
||||
|
Loading…
Reference in New Issue
Block a user