Skip to content

Commit

Permalink
Error code E0794 for late-bound lifetime parameter error.
Browse files Browse the repository at this point in the history
  • Loading branch information
czzrr committed Mar 7, 2023
1 parent 1a521db commit 75563cd
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 35 deletions.
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

0 comments on commit 75563cd

Please sign in to comment.