Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error code E0794 for late-bound lifetime parameter error. #107416

Merged
merged 1 commit into from
Mar 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ E0790: include_str!("./error_codes/E0790.md"),
E0791: include_str!("./error_codes/E0791.md"),
E0792: include_str!("./error_codes/E0792.md"),
E0793: include_str!("./error_codes/E0793.md"),
E0794: include_str!("./error_codes/E0794.md"),
}

// Undocumented removed error codes. Note that many removed error codes are documented.
Expand Down
64 changes: 64 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0794.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
A lifetime parameter of a function definition is called *late-bound* if it both:

1. appears in an argument type
2. does not appear in a generic type constraint

You cannot specify lifetime arguments for late-bound lifetime parameters.

Erroneous code example:

```compile_fail,E0794
fn foo<'a>(x: &'a str) -> &'a str { x }
let _ = foo::<'static>;
```

The type of a concrete instance of a generic function is universally quantified
over late-bound lifetime parameters. This is because we want the function to
work for any lifetime substituted for the late-bound lifetime parameter, no
matter where the function is called. Consequently, it doesn't make sense to
specify arguments for late-bound lifetime parameters, since they are not
resolved until the function's call site(s).

To fix the issue, remove the specified lifetime:

```
fn foo<'a>(x: &'a str) -> &'a str { x }
let _ = foo;
```

### Additional information

Lifetime parameters that are not late-bound are called *early-bound*.
Confusion may arise from the fact that late-bound and early-bound
lifetime parameters are declared the same way in function definitions.
When referring to a function pointer type, universal quantification over
late-bound lifetime parameters can be made explicit:

```
trait BarTrait<'a> {}

struct Bar<'a> {
s: &'a str
}

impl<'a> BarTrait<'a> for Bar<'a> {}

fn bar<'a, 'b, T>(x: &'a str, _t: T) -> &'a str
where T: BarTrait<'b>
{
x
}

let bar_fn: for<'a> fn(&'a str, Bar<'static>) -> &'a str = bar; // OK
let bar_fn2 = bar::<'static, Bar>; // Not allowed
let bar_fn3 = bar::<Bar>; // OK
```

In the definition of `bar`, the lifetime parameter `'a` is late-bound, while
`'b` is early-bound. This is reflected in the type annotation for `bar_fn`,
where `'a` is universally quantified and `'b` is substituted by a specific
lifetime. It is not allowed to explicitly specify early-bound lifetime
arguments when late-bound lifetime parameters are present (as for `bar_fn2`,
see issue #42868: https://github.com/rust-lang/rust/issues/42868), although the
types that are constrained by early-bound parameters can be specified (as for
`bar_fn3`).
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
if position == GenericArgPosition::Value
&& args.num_lifetime_params() != param_counts.lifetimes
{
let mut err = tcx.sess.struct_span_err(span, msg);
let mut err = struct_span_err!(tcx.sess, span, E0794, "{}", msg);
err.span_note(span_late, note);
err.emit();
} else {
Expand Down
17 changes: 9 additions & 8 deletions tests/ui/const-generics/const-arg-in-const-arg.full.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:18:23
|
LL | let _: [u8; faz::<'a>(&())];
Expand All @@ -10,7 +10,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:21:23
|
LL | let _: [u8; faz::<'b>(&())];
Expand All @@ -22,7 +22,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:41:24
|
LL | let _: Foo<{ faz::<'a>(&()) }>;
Expand All @@ -34,7 +34,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:44:24
|
LL | let _: Foo<{ faz::<'b>(&()) }>;
Expand Down Expand Up @@ -94,7 +94,7 @@ LL | let _ = [0; bar::<N>()];
|
= help: try adding a `where` bound using this expression: `where [(); bar::<N>()]:`

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:30:23
|
LL | let _ = [0; faz::<'a>(&())];
Expand All @@ -106,7 +106,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:33:23
|
LL | let _ = [0; faz::<'b>(&())];
Expand Down Expand Up @@ -134,7 +134,7 @@ LL | let _ = Foo::<{ bar::<N>() }>;
|
= help: try adding a `where` bound using this expression: `where [(); { bar::<N>() }]:`

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:52:27
|
LL | let _ = Foo::<{ faz::<'a>(&()) }>;
Expand All @@ -146,7 +146,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:55:27
|
LL | let _ = Foo::<{ faz::<'b>(&()) }>;
Expand All @@ -160,3 +160,4 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }

error: aborting due to 16 previous errors

For more information about this error, try `rustc --explain E0794`.
18 changes: 9 additions & 9 deletions tests/ui/const-generics/const-arg-in-const-arg.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
LL | let _: [u8; bar::<{ N }>()];
| + +

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:18:23
|
LL | let _: [u8; faz::<'a>(&())];
Expand All @@ -228,7 +228,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:21:23
|
LL | let _: [u8; faz::<'b>(&())];
Expand All @@ -251,7 +251,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
LL | let _: Foo<{ bar::<{ N }>() }>;
| + +

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:41:24
|
LL | let _: Foo<{ faz::<'a>(&()) }>;
Expand All @@ -263,7 +263,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:44:24
|
LL | let _: Foo<{ faz::<'b>(&()) }>;
Expand Down Expand Up @@ -294,7 +294,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
LL | let _ = [0; bar::<{ N }>()];
| + +

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:30:23
|
LL | let _ = [0; faz::<'a>(&())];
Expand All @@ -306,7 +306,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:33:23
|
LL | let _ = [0; faz::<'b>(&())];
Expand All @@ -329,7 +329,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
LL | let _ = Foo::<{ bar::<{ N }>() }>;
| + +

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:52:27
|
LL | let _ = Foo::<{ faz::<'a>(&()) }>;
Expand All @@ -341,7 +341,7 @@ note: the late bound lifetime parameter is introduced here
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:55:27
|
LL | let _ = Foo::<{ faz::<'b>(&()) }>;
Expand All @@ -355,5 +355,5 @@ LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }

error: aborting due to 36 previous errors

Some errors have detailed explanations: E0658, E0747.
Some errors have detailed explanations: E0658, E0747, E0794.
For more information about an error, try `rustc --explain E0658`.
8 changes: 8 additions & 0 deletions tests/ui/late-bound-lifetimes/issue-80618.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn foo<'a>(x: &'a str) -> &'a str {
x
}

fn main() {
let _ = foo::<'static>;
//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present [E0794]
}
15 changes: 15 additions & 0 deletions tests/ui/late-bound-lifetimes/issue-80618.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/issue-80618.rs:6:19
|
LL | let _ = foo::<'static>;
| ^^^^^^^
|
note: the late bound lifetime parameter is introduced here
--> $DIR/issue-80618.rs:1:8
|
LL | fn foo<'a>(x: &'a str) -> &'a str {
| ^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0794`.
31 changes: 16 additions & 15 deletions tests/ui/methods/method-call-lifetime-args-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ note: method defined here, with 2 lifetime parameters: `'a`, `'b`
LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
| ^^^^^ -- --

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:27:15
|
LL | S::late::<'static>(S, &0, &0);
Expand All @@ -42,7 +42,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:29:15
|
LL | S::late::<'static, 'static>(S, &0, &0);
Expand All @@ -54,7 +54,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:31:15
|
LL | S::late::<'static, 'static, 'static>(S, &0, &0);
Expand All @@ -66,7 +66,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:34:21
|
LL | S::late_early::<'static, 'static>(S, &0);
Expand All @@ -78,7 +78,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:36:21
|
LL | S::late_early::<'static, 'static, 'static>(S, &0);
Expand All @@ -90,7 +90,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:40:24
|
LL | S::late_implicit::<'static>(S, &0, &0);
Expand All @@ -102,7 +102,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit(self, _: &u8, _: &u8) {}
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:42:24
|
LL | S::late_implicit::<'static, 'static>(S, &0, &0);
Expand All @@ -114,7 +114,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit(self, _: &u8, _: &u8) {}
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:44:24
|
LL | S::late_implicit::<'static, 'static, 'static>(S, &0, &0);
Expand All @@ -126,7 +126,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit(self, _: &u8, _: &u8) {}
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:47:30
|
LL | S::late_implicit_early::<'static, 'static>(S, &0);
Expand All @@ -138,7 +138,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:49:30
|
LL | S::late_implicit_early::<'static, 'static, 'static>(S, &0);
Expand All @@ -150,7 +150,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:52:35
|
LL | S::late_implicit_self_early::<'static, 'static>(&S);
Expand All @@ -162,7 +162,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:54:35
|
LL | S::late_implicit_self_early::<'static, 'static, 'static>(&S);
Expand All @@ -174,7 +174,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
| ^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:57:28
|
LL | S::late_unused_early::<'static, 'static>(S);
Expand All @@ -186,7 +186,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
| ^^

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-fail.rs:59:28
|
LL | S::late_unused_early::<'static, 'static, 'static>(S);
Expand Down Expand Up @@ -232,4 +232,5 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }

error: aborting due to 18 previous errors

For more information about this error, try `rustc --explain E0107`.
Some errors have detailed explanations: E0107, E0794.
For more information about an error, try `rustc --explain E0107`.
Loading