diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 854625579ee7b..1e86d159668ff 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -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"), @@ -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 diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md new file mode 100644 index 0000000000000..08159d3f469ac --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -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(x: &()) -> &() { + with_restriction::(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::(x) +} + +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x +} +``` diff --git a/src/test/ui/error-codes/E0311.rs b/src/test/ui/error-codes/E0311.rs new file mode 100644 index 0000000000000..566b518b4331d --- /dev/null +++ b/src/test/ui/error-codes/E0311.rs @@ -0,0 +1,9 @@ +fn no_restriction(x: &()) -> &() { + with_restriction::(x) //~ ERROR E0311 +} + +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0311.stderr b/src/test/ui/error-codes/E0311.stderr new file mode 100644 index 0000000000000..9873b5ae6ff13 --- /dev/null +++ b/src/test/ui/error-codes/E0311.stderr @@ -0,0 +1,24 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/E0311.rs:2:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/E0311.rs:1:25 + | +LL | fn no_restriction(x: &()) -> &() { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/E0311.rs:2:5 + | +LL | with_restriction::(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`. diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr index a8b0996d8b0c7..31fd8a4d633e9 100644 --- a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr +++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr @@ -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`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index e5d2ead6ad67c..872263fd7311b 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -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`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index ed1b91676a214..171f4b333db4e 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -164,5 +164,5 @@ LL | G: Get + '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`.