Skip to content

Commit ce91e46

Browse files
committed
check RPITs for invalid args
1 parent c337825 commit ce91e46

14 files changed

+134
-47
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -441,27 +441,17 @@ fn check_opaque_type_parameter_valid<'tcx>(
441441
opaque_type_key: OpaqueTypeKey<'tcx>,
442442
span: Span,
443443
) -> Result<(), ErrorGuaranteed> {
444-
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
445-
let (_parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin {
446-
OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true),
447-
OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false),
448-
};
449-
450444
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
451445
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
452446
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
453447

454448
for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
455449
let arg_is_param = match arg.unpack() {
456450
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
457-
GenericArgKind::Lifetime(lt) if is_ty_alias => {
451+
GenericArgKind::Lifetime(lt) => {
458452
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
459453
|| (lt.is_static() && opaque_env.param_equal_static(i))
460454
}
461-
// FIXME(#113916): we can't currently check for unique lifetime params,
462-
// see that issue for more. We will also have to ignore unused lifetime
463-
// params for RPIT, but that's comparatively trivial ✨
464-
GenericArgKind::Lifetime(_) => continue,
465455
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
466456
};
467457

Lines changed: 12 additions & 0 deletions
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 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0792`.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// This was an ICE. See #110726.
2+
// FIXME(aliemjay): outdated due to "once modulo regions" restriction.
3+
4+
//@ revisions: statik infer fixed
5+
//@ [fixed] check-pass
6+
#![allow(unconditional_recursion)]
7+
8+
fn foo<'a>() -> impl Sized + 'a {
9+
#[cfg(statik)]
10+
let i: i32 = foo::<'static>();
11+
//[statik]~^ ERROR opaque type used twice with different lifetimes
12+
//[statik]~| ERROR opaque type used twice with different lifetimes
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() {}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error: opaque type used twice with different lifetimes
2+
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
3+
|
4+
LL | let i: i32 = foo::<'static>();
5+
| ^^^^^^^^^^^^^^^^ lifetime `'static` used here
6+
...
7+
LL | i
8+
| - lifetime `'a` previously used here
9+
|
10+
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
11+
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
12+
|
13+
LL | let i: i32 = foo::<'static>();
14+
| ^^^^^^^^^^^^^^^^
15+
16+
error: opaque type used twice with different lifetimes
17+
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
18+
|
19+
LL | let i: i32 = foo::<'static>();
20+
| ^^^^^^^^^^^^^^^^ lifetime `'static` used here
21+
...
22+
LL | i
23+
| - lifetime `'a` previously used here
24+
|
25+
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
26+
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
27+
|
28+
LL | let i: i32 = foo::<'static>();
29+
| ^^^^^^^^^^^^^^^^
30+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
31+
32+
error: aborting due to 2 previous errors
33+

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

Lines changed: 1 addition & 3 deletions
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) {
Lines changed: 7 additions & 17 deletions
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 1 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`.

tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ trait Foo {
55
fn bar<'other: 'a>() -> impl Sized + 'a {}
66
//~^ ERROR use of undeclared lifetime name `'a`
77
//~| ERROR use of undeclared lifetime name `'a`
8+
//~| ERROR expected generic lifetime parameter, found `'static`
89
}
910

1011
fn main() {}

tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ help: consider introducing lifetime `'a` here
2828
LL | trait Foo<'a> {
2929
| ++++
3030

31-
error: aborting due to 2 previous errors
31+
error[E0792]: expected generic lifetime parameter, found `'static`
32+
--> $DIR/bad-item-bound-within-rpitit-2.rs:5:45
33+
|
34+
LL | fn bar<'other: 'a>() -> impl Sized + 'a {}
35+
| ------ ^^
36+
| |
37+
| cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
38+
39+
error: aborting due to 3 previous errors
3240

33-
For more information about this error, try `rustc --explain E0261`.
41+
Some errors have detailed explanations: E0261, E0792.
42+
For more information about an error, try `rustc --explain E0261`.

tests/ui/impl-trait/rpit/early_bound.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
55
let true = n else { loop {} };
66
let _ = || {
77
let _ = identity::<&'a ()>(test(false));
8+
//~^ ERROR expected generic lifetime parameter, found `'_`
89
};
910
loop {}
1011
}

tests/ui/impl-trait/rpit/early_bound.stderr

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
error[E0792]: expected generic lifetime parameter, found `'_`
2+
--> $DIR/early_bound.rs:7:17
3+
|
4+
LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a {
5+
| -- this generic parameter must be used with a generic lifetime parameter
6+
...
7+
LL | let _ = identity::<&'a ()>(test(false));
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9+
110
error: concrete type differs from previous defining opaque type use
211
--> $DIR/early_bound.rs:3:29
312
|
@@ -10,5 +19,6 @@ note: previous use here
1019
LL | let _ = identity::<&'a ()>(test(false));
1120
| ^^^^^^^^^^^
1221

13-
error: aborting due to 1 previous error
22+
error: aborting due to 2 previous errors
1423

24+
For more information about this error, try `rustc --explain E0792`.

tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// issue: #111935
22
// FIXME(aliemjay): outdated due to "once modulo regions" restriction.
3-
// FIXME(aliemjay): mod `infer` should fail.
43

54
#![allow(unconditional_recursion)]
65

@@ -22,6 +21,7 @@ mod infer {
2221
// invalid defining use: Opaque<'_> := ()
2322
fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
2423
let _: () = foo(Lt::<'_>::None);
24+
//~^ ERROR expected generic lifetime parameter, found `'_`
2525
}
2626
}
2727

tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: opaque type used twice with different lifetimes
2-
--> $DIR/non-defining-use-lifetimes.rs:15:16
2+
--> $DIR/non-defining-use-lifetimes.rs:14:16
33
|
44
LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
55
| ______________________________________________-
@@ -10,11 +10,19 @@ LL | | }
1010
| |_____- lifetime `'a` previously used here
1111
|
1212
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
13-
--> $DIR/non-defining-use-lifetimes.rs:15:16
13+
--> $DIR/non-defining-use-lifetimes.rs:14:16
1414
|
1515
LL | let _: () = foo(Lt::<'static>::None);
1616
| ^^
1717

18+
error[E0792]: expected generic lifetime parameter, found `'_`
19+
--> $DIR/non-defining-use-lifetimes.rs:23:16
20+
|
21+
LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
22+
| -- this generic parameter must be used with a generic lifetime parameter
23+
LL | let _: () = foo(Lt::<'_>::None);
24+
| ^^
25+
1826
error: opaque type used twice with different lifetimes
1927
--> $DIR/non-defining-use-lifetimes.rs:33:16
2028
|
@@ -32,5 +40,6 @@ note: if all non-lifetime generic parameters are the same, but the lifetime para
3240
LL | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
3341
| ^^
3442

35-
error: aborting due to 2 previous errors
43+
error: aborting due to 3 previous errors
3644

45+
For more information about this error, try `rustc --explain E0792`.

tests/ui/type-alias-impl-trait/hkl_forbidden4.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type FutNothing<'a> = impl 'a + Future<Output = ()>;
1313
async fn operation(_: &mut ()) -> () {
1414
//~^ ERROR: concrete type differs from previous
1515
call(operation).await
16+
//~^ ERROR: expected generic lifetime parameter, found `'any`
1617
}
1718

1819
async fn call<F>(_f: F)

tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,17 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
66
|
77
= note: `FutNothing` must be used in combination with a concrete type within the same module
88

9-
error: concrete type differs from previous defining opaque type use
10-
--> $DIR/hkl_forbidden4.rs:13:1
11-
|
12-
LL | async fn operation(_: &mut ()) -> () {
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
14-
|
15-
note: previous use here
9+
error[E0792]: expected generic lifetime parameter, found `'any`
1610
--> $DIR/hkl_forbidden4.rs:15:5
1711
|
12+
LL | async fn operation(_: &mut ()) -> () {
13+
| - this generic parameter must be used with a generic lifetime parameter
14+
LL |
1815
LL | call(operation).await
1916
| ^^^^^^^^^^^^^^^
2017

2118
error[E0792]: expected generic lifetime parameter, found `'any`
22-
--> $DIR/hkl_forbidden4.rs:21:1
19+
--> $DIR/hkl_forbidden4.rs:22:1
2320
|
2421
LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
2522
| -- this generic parameter must be used with a generic lifetime parameter
@@ -29,6 +26,18 @@ LL | |
2926
LL | | }
3027
| |_^
3128

32-
error: aborting due to 3 previous errors
29+
error: concrete type differs from previous defining opaque type use
30+
--> $DIR/hkl_forbidden4.rs:13:1
31+
|
32+
LL | async fn operation(_: &mut ()) -> () {
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
34+
|
35+
note: previous use here
36+
--> $DIR/hkl_forbidden4.rs:15:5
37+
|
38+
LL | call(operation).await
39+
| ^^^^^^^^^^^^^^^
40+
41+
error: aborting due to 4 previous errors
3342

3443
For more information about this error, try `rustc --explain E0792`.

0 commit comments

Comments
 (0)