about summary refs log tree commit diff
path: root/compiler/rustc_error_codes
diff options
context:
space:
mode:
authorMatthew Kelly <matthew.kelly2@gmail.com>2022-08-23 05:19:04 -0400
committerMatthew Kelly <matthew.kelly2@gmail.com>2022-08-23 05:19:04 -0400
commitdbcc4095560a3ddcbdfe3359641b4da00634dcde (patch)
tree62c4c5afc567eff5106a2bd3dbfeadece72793eb /compiler/rustc_error_codes
parenta9cefd04411611e72417ee2762979e300aac8749 (diff)
downloadrust-dbcc4095560a3ddcbdfe3359641b4da00634dcde.tar.gz
rust-dbcc4095560a3ddcbdfe3359641b4da00634dcde.zip
Improve E0311.md description
Diffstat (limited to 'compiler/rustc_error_codes')
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0311.md37
1 files changed, 29 insertions, 8 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md
index 9477a0b1fb7..00b23c42052 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0311.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0311.md
@@ -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.
-
-Working implementation of the `NestedBorrowMut` trait:
+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`.
+
+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;