Skip to content

Commit 49bc668

Browse files
authored
Rollup merge of #100747 - MatthewPeterKelly:mpk/add-long-error-message-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.
2 parents 90c34fa + c0d32fd commit 49bc668

File tree

7 files changed

+79
-2
lines changed

7 files changed

+79
-2
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ E0307: include_str!("./error_codes/E0307.md"),
159159
E0308: include_str!("./error_codes/E0308.md"),
160160
E0309: include_str!("./error_codes/E0309.md"),
161161
E0310: include_str!("./error_codes/E0310.md"),
162+
E0311: include_str!("./error_codes/E0311.md"),
162163
E0312: include_str!("./error_codes/E0312.md"),
163164
E0316: include_str!("./error_codes/E0316.md"),
164165
E0317: include_str!("./error_codes/E0317.md"),
@@ -568,7 +569,6 @@ E0790: include_str!("./error_codes/E0790.md"),
568569
// E0300, // unexpanded macro
569570
// E0304, // expected signed integer constant
570571
// E0305, // expected constant
571-
E0311, // thing may not live long enough
572572
E0313, // lifetime of borrowed pointer outlives lifetime of captured
573573
// variable
574574
// E0314, // closure outlives stack frame
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
This error occurs when there is an unsatisfied outlives bound involving an
2+
elided region and a generic type parameter or associated type.
3+
4+
Erroneous code example:
5+
6+
```compile_fail,E0311
7+
fn no_restriction<T>(x: &()) -> &() {
8+
with_restriction::<T>(x)
9+
}
10+
11+
fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
12+
x
13+
}
14+
```
15+
16+
Why doesn't this code compile? It helps to look at the lifetime bounds that are
17+
automatically added by the compiler. For more details see the documentation for
18+
[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html).
19+
20+
The compiler elides the lifetime of `x` and the return type to some arbitrary
21+
lifetime `'anon` in `no_restriction()`. The only information available to the
22+
compiler is that `'anon` is valid for the duration of the function. When
23+
calling `with_restriction()`, the compiler requires the completely unrelated
24+
type parameter `T` to outlive `'anon` because of the `T: 'a` bound in
25+
`with_restriction()`. This causes an error because `T` is not required to
26+
outlive `'anon` in `no_restriction()`.
27+
28+
If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
29+
compiler would have added an implied bound, causing this to compile.
30+
31+
This error can be resolved by explicitly naming the elided lifetime for `x` and
32+
then explicily requiring that the generic parameter `T` outlives that lifetime:
33+
34+
```
35+
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
36+
with_restriction::<T>(x)
37+
}
38+
39+
fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
40+
x
41+
}
42+
```

src/test/ui/error-codes/E0311.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn no_restriction<T>(x: &()) -> &() {
2+
with_restriction::<T>(x) //~ ERROR E0311
3+
}
4+
5+
fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
6+
x
7+
}
8+
9+
fn main() {}

src/test/ui/error-codes/E0311.stderr

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0311]: the parameter type `T` may not live long enough
2+
--> $DIR/E0311.rs:2:5
3+
|
4+
LL | with_restriction::<T>(x)
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: the parameter type `T` must be valid for the anonymous lifetime defined here...
8+
--> $DIR/E0311.rs:1:25
9+
|
10+
LL | fn no_restriction<T>(x: &()) -> &() {
11+
| ^^^
12+
note: ...so that the type `T` will meet its required lifetime bounds
13+
--> $DIR/E0311.rs:2:5
14+
|
15+
LL | with_restriction::<T>(x)
16+
| ^^^^^^^^^^^^^^^^^^^^^
17+
help: consider adding an explicit lifetime bound...
18+
|
19+
LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
20+
| +++ ++++
21+
22+
error: aborting due to previous error
23+
24+
For more information about this error, try `rustc --explain E0311`.

src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
2121

2222
error: aborting due to previous error
2323

24+
For more information about this error, try `rustc --explain E0311`.

src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ LL | fn func<'a, T: Test + 'a>(foo: &Foo, t: T) {
2727

2828
error: aborting due to previous error
2929

30+
For more information about this error, try `rustc --explain E0311`.

src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,5 @@ LL | G: Get<T> + 'a,
164164

165165
error: aborting due to 8 previous errors
166166

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

0 commit comments

Comments
 (0)