Skip to content

Commit 9599f3c

Browse files
authored
Rollup merge of #107416 - czzrr:issue-80618, r=GuillaumeGomez
Error code E0794 for late-bound lifetime parameter error. This PR addresses [#80618](#80618).
2 parents df61fca + 75563cd commit 9599f3c

File tree

9 files changed

+126
-35
lines changed

9 files changed

+126
-35
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ E0790: include_str!("./error_codes/E0790.md"),
513513
E0791: include_str!("./error_codes/E0791.md"),
514514
E0792: include_str!("./error_codes/E0792.md"),
515515
E0793: include_str!("./error_codes/E0793.md"),
516+
E0794: include_str!("./error_codes/E0794.md"),
516517
}
517518

518519
// Undocumented removed error codes. Note that many removed error codes are documented.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
A lifetime parameter of a function definition is called *late-bound* if it both:
2+
3+
1. appears in an argument type
4+
2. does not appear in a generic type constraint
5+
6+
You cannot specify lifetime arguments for late-bound lifetime parameters.
7+
8+
Erroneous code example:
9+
10+
```compile_fail,E0794
11+
fn foo<'a>(x: &'a str) -> &'a str { x }
12+
let _ = foo::<'static>;
13+
```
14+
15+
The type of a concrete instance of a generic function is universally quantified
16+
over late-bound lifetime parameters. This is because we want the function to
17+
work for any lifetime substituted for the late-bound lifetime parameter, no
18+
matter where the function is called. Consequently, it doesn't make sense to
19+
specify arguments for late-bound lifetime parameters, since they are not
20+
resolved until the function's call site(s).
21+
22+
To fix the issue, remove the specified lifetime:
23+
24+
```
25+
fn foo<'a>(x: &'a str) -> &'a str { x }
26+
let _ = foo;
27+
```
28+
29+
### Additional information
30+
31+
Lifetime parameters that are not late-bound are called *early-bound*.
32+
Confusion may arise from the fact that late-bound and early-bound
33+
lifetime parameters are declared the same way in function definitions.
34+
When referring to a function pointer type, universal quantification over
35+
late-bound lifetime parameters can be made explicit:
36+
37+
```
38+
trait BarTrait<'a> {}
39+
40+
struct Bar<'a> {
41+
s: &'a str
42+
}
43+
44+
impl<'a> BarTrait<'a> for Bar<'a> {}
45+
46+
fn bar<'a, 'b, T>(x: &'a str, _t: T) -> &'a str
47+
where T: BarTrait<'b>
48+
{
49+
x
50+
}
51+
52+
let bar_fn: for<'a> fn(&'a str, Bar<'static>) -> &'a str = bar; // OK
53+
let bar_fn2 = bar::<'static, Bar>; // Not allowed
54+
let bar_fn3 = bar::<Bar>; // OK
55+
```
56+
57+
In the definition of `bar`, the lifetime parameter `'a` is late-bound, while
58+
`'b` is early-bound. This is reflected in the type annotation for `bar_fn`,
59+
where `'a` is universally quantified and `'b` is substituted by a specific
60+
lifetime. It is not allowed to explicitly specify early-bound lifetime
61+
arguments when late-bound lifetime parameters are present (as for `bar_fn2`,
62+
see issue #42868: https://github.com/rust-lang/rust/issues/42868), although the
63+
types that are constrained by early-bound parameters can be specified (as for
64+
`bar_fn3`).

compiler/rustc_hir_analysis/src/astconv/generics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
612612
if position == GenericArgPosition::Value
613613
&& args.num_lifetime_params() != param_counts.lifetimes
614614
{
615-
let mut err = tcx.sess.struct_span_err(span, msg);
615+
let mut err = struct_span_err!(tcx.sess, span, E0794, "{}", msg);
616616
err.span_note(span_late, note);
617617
err.emit();
618618
} else {

tests/ui/const-generics/const-arg-in-const-arg.full.stderr

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
1+
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
22
--> $DIR/const-arg-in-const-arg.rs:18:23
33
|
44
LL | let _: [u8; faz::<'a>(&())];
@@ -10,7 +10,7 @@ note: the late bound lifetime parameter is introduced here
1010
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
1111
| ^^
1212

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

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

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

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

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

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

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

161161
error: aborting due to 16 previous errors
162162

163+
For more information about this error, try `rustc --explain E0794`.

tests/ui/const-generics/const-arg-in-const-arg.min.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ help: if this generic argument was intended as a const parameter, surround it wi
216216
LL | let _: [u8; bar::<{ N }>()];
217217
| + +
218218

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

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

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

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

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

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

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

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

356356
error: aborting due to 36 previous errors
357357

358-
Some errors have detailed explanations: E0658, E0747.
358+
Some errors have detailed explanations: E0658, E0747, E0794.
359359
For more information about an error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn foo<'a>(x: &'a str) -> &'a str {
2+
x
3+
}
4+
5+
fn main() {
6+
let _ = foo::<'static>;
7+
//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present [E0794]
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
2+
--> $DIR/issue-80618.rs:6:19
3+
|
4+
LL | let _ = foo::<'static>;
5+
| ^^^^^^^
6+
|
7+
note: the late bound lifetime parameter is introduced here
8+
--> $DIR/issue-80618.rs:1:8
9+
|
10+
LL | fn foo<'a>(x: &'a str) -> &'a str {
11+
| ^^
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0794`.

tests/ui/methods/method-call-lifetime-args-fail.stderr

+16-15
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ note: method defined here, with 2 lifetime parameters: `'a`, `'b`
3030
LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
3131
| ^^^^^ -- --
3232

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

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

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

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

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

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

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

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

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

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

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

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

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

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

233233
error: aborting due to 18 previous errors
234234

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

0 commit comments

Comments
 (0)