Skip to content

Commit 2534296

Browse files
committed
error on invalid RPIT lifetime args
Invalid args include infer lifetimes and 'static. This was previously an ICE for inferred lifetime. What about 'static?
1 parent d51fa36 commit 2534296

File tree

6 files changed

+72
-32
lines changed

6 files changed

+72
-32
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,9 @@ fn check_opaque_type_well_formed<'tcx>(
339339
}
340340
}
341341

342-
fn check_opaque_type_parameter_valid(
343-
tcx: TyCtxt<'_>,
344-
opaque_type_key: OpaqueTypeKey<'_>,
342+
fn check_opaque_type_parameter_valid<'tcx>(
343+
tcx: TyCtxt<'tcx>,
344+
opaque_type_key: OpaqueTypeKey<'tcx>,
345345
span: Span,
346346
) -> Result<(), ErrorGuaranteed> {
347347
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
@@ -352,25 +352,28 @@ fn check_opaque_type_parameter_valid(
352352

353353
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
354354
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
355-
for (i, arg) in opaque_type_key.args.iter().enumerate() {
355+
for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
356356
if let Err(guar) = arg.error_reported() {
357357
return Err(guar);
358358
}
359359

360360
let arg_is_param = match arg.unpack() {
361361
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
362-
GenericArgKind::Lifetime(lt) if is_ty_alias => {
363-
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
364-
}
365-
// FIXME(#113916): we can't currently check for unique lifetime params,
366-
// see that issue for more. We will also have to ignore unused lifetime
367-
// params for RPIT, but that's comparatively trivial ✨
368-
GenericArgKind::Lifetime(_) => continue,
362+
GenericArgKind::Lifetime(lt) => match is_ty_alias {
363+
true => matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)),
364+
// FIXME(#111935, #113916): For RPIT, we currently accept ReStatic as well.
365+
// This is a back-compat hack, see the issue for more.
366+
false => matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic),
367+
},
369368
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
370369
};
371370

372371
if arg_is_param {
373-
seen_params.entry(arg).or_default().push(i);
372+
// FIXME(#113916): For RPIT, we can't currently check for unique lifetime
373+
// params, see that issue for more. We limit this to TAIT for now.
374+
if is_ty_alias {
375+
seen_params.entry(arg).or_default().push(i);
376+
}
374377
} else {
375378
// Prevent `fn foo() -> Foo<u32>` from being defining.
376379
let opaque_param = opaque_generics.param_at(i, tcx);

compiler/rustc_middle/src/ty/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,19 @@ impl<'tcx> OpaqueTypeKey<'tcx> {
15211521
let args = tcx.mk_args_from_iter(args);
15221522
Self { def_id, args }
15231523
}
1524+
1525+
pub fn iter_captured_args(
1526+
self,
1527+
tcx: TyCtxt<'tcx>,
1528+
) -> impl Iterator<Item = (usize, GenericArg<'tcx>)> {
1529+
std::iter::zip(self.args, tcx.variances_of(self.def_id)).enumerate().filter_map(
1530+
|(i, (arg, v))| match (arg.unpack(), v) {
1531+
(_, ty::Invariant) => Some((i, arg)),
1532+
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None,
1533+
_ => bug!("unexpected opaque type arg variance"),
1534+
},
1535+
)
1536+
}
15241537
}
15251538

15261539
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0792]: expected generic lifetime parameter, found `'_`
2+
--> $DIR/defining-use-captured-non-universal-region.rs:15:18
3+
|
4+
LL | fn foo<'a>() -> impl Sized + 'a {
5+
| -- this generic parameter must be used with a generic lifetime parameter
6+
...
7+
LL | let i: i32 = foo::<'_>();
8+
| ^^^^^^^^^^^
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0792`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// This was an ICE. See #110726.
2+
//
3+
// FIXME(#111935) revision `statik` should not pass.
4+
5+
// revisions: statik infer fixed
6+
//[fixed] check-pass
7+
//[statik] check-pass
8+
#![allow(unconditional_recursion)]
9+
10+
fn foo<'a>() -> impl Sized + 'a {
11+
#[cfg(statik)]
12+
let i: i32 = foo::<'static>();
13+
14+
#[cfg(infer)]
15+
let i: i32 = foo::<'_>();
16+
//[infer]~^ ERROR expected generic lifetime parameter, found `'_`
17+
18+
#[cfg(fixed)]
19+
let i: i32 = foo::<'a>();
20+
21+
i
22+
}
23+
24+
fn main() {}

tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
use std::fmt::Debug;
33

44
fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
5-
//~^ ERROR cannot resolve opaque type
6-
75
|x| x
8-
//~^ ERROR concrete type differs from previous defining opaque type use
6+
//~^ ERROR expected generic lifetime parameter, found `'_`
97
}
108

119
fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
1-
error: concrete type differs from previous defining opaque type use
2-
--> $DIR/impl-fn-predefined-lifetimes.rs:7:9
3-
|
4-
LL | |x| x
5-
| ^ expected `impl Debug + '_`, got `&u8`
6-
|
7-
note: previous use here
8-
--> $DIR/impl-fn-predefined-lifetimes.rs:7:5
9-
|
10-
LL | |x| x
11-
| ^^^^^
12-
13-
error[E0720]: cannot resolve opaque type
14-
--> $DIR/impl-fn-predefined-lifetimes.rs:4:35
1+
error[E0792]: expected generic lifetime parameter, found `'_`
2+
--> $DIR/impl-fn-predefined-lifetimes.rs:5:9
153
|
164
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
17-
| ^^^^^^^^^^^^^^^ cannot resolve opaque type
5+
| -- this generic parameter must be used with a generic lifetime parameter
6+
LL | |x| x
7+
| ^
188

19-
error: aborting due to 2 previous errors
9+
error: aborting due to previous error
2010

21-
For more information about this error, try `rustc --explain E0720`.
11+
For more information about this error, try `rustc --explain E0792`.

0 commit comments

Comments
 (0)