Skip to content

Commit

Permalink
Rollup merge of #100747 - MatthewPeterKelly:mpk/add-long-error-messag…
Browse files Browse the repository at this point in the history
…e-for-E0311, r=MatthewPeterKelly

Add long description and test for E0311

Adds a long description and unit test for the E0311 compiler error.

Fixes one line-item in #61137.
  • Loading branch information
JohnTitor authored Sep 28, 2022
2 parents 90c34fa + c0d32fd commit 49bc668
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 2 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ E0307: include_str!("./error_codes/E0307.md"),
E0308: include_str!("./error_codes/E0308.md"),
E0309: include_str!("./error_codes/E0309.md"),
E0310: include_str!("./error_codes/E0310.md"),
E0311: include_str!("./error_codes/E0311.md"),
E0312: include_str!("./error_codes/E0312.md"),
E0316: include_str!("./error_codes/E0316.md"),
E0317: include_str!("./error_codes/E0317.md"),
Expand Down Expand Up @@ -568,7 +569,6 @@ E0790: include_str!("./error_codes/E0790.md"),
// E0300, // unexpanded macro
// E0304, // expected signed integer constant
// E0305, // expected constant
E0311, // thing may not live long enough
E0313, // lifetime of borrowed pointer outlives lifetime of captured
// variable
// E0314, // closure outlives stack frame
Expand Down
42 changes: 42 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0311.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
This error occurs when there is an unsatisfied outlives bound involving an
elided region and a generic type parameter or associated type.

Erroneous code example:

```compile_fail,E0311
fn no_restriction<T>(x: &()) -> &() {
with_restriction::<T>(x)
}
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 are
automatically added by the compiler. For more details see the documentation for
[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html).

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()`.

If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
compiler would have added an implied bound, causing this to compile.

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 no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
with_restriction::<T>(x)
}
fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
x
}
```
9 changes: 9 additions & 0 deletions src/test/ui/error-codes/E0311.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn no_restriction<T>(x: &()) -> &() {
with_restriction::<T>(x) //~ ERROR E0311
}

fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
x
}

fn main() {}
24 changes: 24 additions & 0 deletions src/test/ui/error-codes/E0311.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/E0311.rs:2:5
|
LL | with_restriction::<T>(x)
| ^^^^^^^^^^^^^^^^^^^^^
|
note: the parameter type `T` must be valid for the anonymous lifetime defined here...
--> $DIR/E0311.rs:1:25
|
LL | fn no_restriction<T>(x: &()) -> &() {
| ^^^
note: ...so that the type `T` will meet its required lifetime bounds
--> $DIR/E0311.rs:2:5
|
LL | with_restriction::<T>(x)
| ^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
| +++ ++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0311`.
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {

error: aborting due to previous error

For more information about this error, try `rustc --explain E0311`.
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ LL | fn func<'a, T: Test + 'a>(foo: &Foo, t: T) {

error: aborting due to previous error

For more information about this error, try `rustc --explain E0311`.
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,5 @@ LL | G: Get<T> + 'a,

error: aborting due to 8 previous errors

Some errors have detailed explanations: E0261, E0309, E0621, E0700.
Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700.
For more information about an error, try `rustc --explain E0261`.

0 comments on commit 49bc668

Please sign in to comment.