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`
|
Why doesn't this code compile? The problem has to do with Rust's rules for
|
||||||
from an outer type `T`, through an intermediate type `U`. The compiler is unable
|
lifetime elision in functions (Chapter 10.3 in the Rust book). One of the
|
||||||
to prove that the livetime of `U` is long enough to support the reference. To
|
inputs is a reference to `self`, so the compiler attempts to assign the
|
||||||
fix the issue we can explicitly add lifetime specifiers to the `NestedBorrowMut`
|
the same lifetime to the `&mut self` input and `&mut V` output to the
|
||||||
trait, which link the lifetimes of the various data types and allow the code to
|
`nested_borrow_mut()` function. The problem is that there is no way for the
|
||||||
compile.
|
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;
|
use std::borrow::BorrowMut;
|
||||||
|
Loading…
Reference in New Issue
Block a user