-This error occurs when there is an unsatisfied outlives bound on a generic
-type parameter or associated type.
+This error occurs when there is an unsatisfied outlives bound involving an
+elided region on a generic type parameter or associated type.
Erroneous code example:
```compile_fail,E0311
-use std::borrow::BorrowMut;
-
-trait NestedBorrowMut<U, V> {
- fn nested_borrow_mut(&mut self) -> &mut V;
+fn no_restriction<T>(x: &()) -> &() {
+ with_restriction::<T>(x)
}
-impl<T, U, V> NestedBorrowMut<U, V> for T
-where
- T: BorrowMut<U>,
- U: BorrowMut<V>,
-{
- fn nested_borrow_mut(&mut self) -> &mut V {
- let u_ref = self.borrow_mut();
- let v_ref = u_ref.borrow_mut();
- v_ref
- }
+fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+ x
}
```
-Why doesn't this code compile? It helps to look at the lifetime bounds that
-the compiler is automatically adding ("Lifetime Ellision", Chapter 10.3 in the
-Rust book) to the `nested_borrow_mut()` and `borrow_mut()` functions. In both
-cases the input is a reference to `self`, so the compiler attempts to assign
-the same lifetime to the input and output.
+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]
-Looking specifically at `nested_borrow_mut()`, we see that there are three
-object references to keep track of, along with their associated lifetimes:
-- `self` (which is a `&mut T`)
-- `u_ref` (which is a `&mut U`)
-- `v_ref` (which is a `&mut V`)
+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 `borrow_mut()` method implicitly requires that that the input and output
-have the same lifetime bounds. Thus the lines: `let u_ref = self.borrow_mut();`
-and `let v_ref = u_ref.borrow_mut();` in `nested_borrow_mut()` above imply that
-`u_ref` and `self` must share a lifetime bound, and also that `v_ref` and
-`u_ref` share a lifetime bound. The problem is that the function signature for
-`nested_borrow_mut()` only gives the compiler information about the lifetimes
-of `self` and `v_ref` -- nothing about `u_ref`.
+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`.
-The way to fix this error is then to explicitly tell the compiler that the
-lifetime of `u_ref` is the same as `self` and `v_ref`, which then allows it
-to satisfy the two lifetime bound requirements described above.
+```
+fn no_restriction(x: &()) -> &() {
+ with_restriction(x)
+}
-Here is the working version of the code:
+fn with_restriction<'a>(x: &'a ()) -> &'a () {
+ x
+}
```
-use std::borrow::BorrowMut;
-trait NestedBorrowMut<'a, U, V> {
- fn nested_borrow_mut(&'a mut self) -> &'a mut V;
+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)
}
-impl<'a, T, U, V> NestedBorrowMut<'a, U, V> for T
-where
- T: BorrowMut<U>,
- U: BorrowMut<V> + 'a,
-{
- fn nested_borrow_mut(&'a mut self) -> &'a mut V {
- let u_ref = self.borrow_mut();
- let v_ref = u_ref.borrow_mut();
- v_ref
- }
+fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+ x
}
```
-error[E0311]: the parameter type `U` may not live long enough
- --> $DIR/E0311.rs:13:21
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/E0311.rs:2:5
|
-LL | let u_ref = self.borrow_mut();
- | ^^^^^^^^^^^^^^^^^
+LL | with_restriction::<T>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^
|
-note: the parameter type `U` must be valid for the anonymous lifetime defined here...
- --> $DIR/E0311.rs:12:26
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/E0311.rs:1:25
|
-LL | fn nested_borrow_mut(&mut self) -> &mut V {
- | ^^^^^^^^^
-note: ...so that the type `U` will meet its required lifetime bounds
- --> $DIR/E0311.rs:13:21
+LL | fn no_restriction<T>(x: &()) -> &() {
+ | ^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+ --> $DIR/E0311.rs:2:5
|
-LL | let u_ref = self.borrow_mut();
- | ^^^^^^^^^^^^^^^^^
+LL | with_restriction::<T>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
-LL | U: BorrowMut<V> + 'a, // Error is caused by missing lifetime here
- | ++++
+LL | fn no_restriction<T: 'a>(x: &()) -> &() {
+ | ++++
-error[E0311]: the parameter type `U` may not live long enough
- --> $DIR/E0311.rs:14:21
- |
-LL | let v_ref = u_ref.borrow_mut();
- | ^^^^^^^^^^^^^^^^^^
- |
-note: the parameter type `U` must be valid for the anonymous lifetime defined here...
- --> $DIR/E0311.rs:12:26
- |
-LL | fn nested_borrow_mut(&mut self) -> &mut V {
- | ^^^^^^^^^
-note: ...so that the type `U` will meet its required lifetime bounds
- --> $DIR/E0311.rs:14:21
- |
-LL | let v_ref = u_ref.borrow_mut();
- | ^^^^^^^^^^^^^^^^^^
-help: consider adding an explicit lifetime bound...
- |
-LL | U: BorrowMut<V> + 'a, // Error is caused by missing lifetime here
- | ++++
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0311`.