Skip to content

Commit dbcc409

Browse files
Improve E0311.md description
1 parent a9cefd0 commit dbcc409

File tree

1 file changed

+29
-8
lines changed
  • compiler/rustc_error_codes/src/error_codes

1 file changed

+29
-8
lines changed

compiler/rustc_error_codes/src/error_codes/E0311.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,35 @@ where
2121
}
2222
```
2323

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.
3253

3354
```
3455
use std::borrow::BorrowMut;

0 commit comments

Comments
 (0)