review updates to E0311 description

This commit is contained in:
Matthew Kelly 2022-08-29 06:05:01 -04:00
parent deadf071ed
commit 4a443dfb82

View file

@ -14,33 +14,25 @@ fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
```
Why doesn't this code compile? It helps to look at the lifetime bounds that are
automatically adding by the compiler. For more details see the Rust
Documentation for Lifetime Elision:
https://doc.rust-lang.org/reference/lifetime-elision.html.
automatically added by the compiler. For more details see the documentation for
[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html).
There are two lifetimes being passed into the `no_restriction()` function: one
associated with the generic type `T` parameter and the other with the input
argument `x`. The compiler does not know which of these lifetimes can be
assigned to the output reference, so we get an error.
The compiler elides the lifetime of `x` and the return type to some arbitrary
lifetime `'anon` in `no_restriction()`. The only information available to the
compiler is that `'anon` is valid for the duration of the function. When
calling `with_restriction()`, the compiler requires the completely unrelated
type parameter `T` to outlive `'anon` because of the `T: 'a bound` in
`with_restriction()`. This causes an error because `T` is not required to
outlive `'anon` in `no_restriction()`.
One way to "fix" this code would be to remove the generic type argument `T`.
In this case, the lifetime elision works because there is a single input
lifetime, which is associated with `x`.
If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
compiler would have added an implied bound [implied
bound](https://rust-lang.github.io/rfcs/2089-implied-bounds.html), causing this
to compile.
```
fn no_restriction(x: &()) -> &() {
with_restriction(x)
}
This error can be resolved by explicitly naming the elided lifetime for `x` and
then explicily requiring that the generic parameter `T` outlives that lifetime:
fn with_restriction<'a>(x: &'a ()) -> &'a () {
x
}
```
The "correct" way to resolve this error is to explicitly tell the compiler
which input lifetime should be assigned to the output. In this case we give
both the generic type `T` parameter and the argument `x` the same lifetime
requirement as the output reference, producing a working version of the code:
```
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
with_restriction::<T>(x)