mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 14:01:51 +00:00
check for non-defining uses of RPIT
This commit is contained in:
parent
3071e0aef6
commit
95fddbc501
@ -371,39 +371,29 @@ fn check_opaque_type_parameter_valid(
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
|
||||
match opaque_ty_hir.expect_opaque_ty().origin {
|
||||
// No need to check return position impl trait (RPIT)
|
||||
// because for type and const parameters they are correct
|
||||
// by construction: we convert
|
||||
//
|
||||
// fn foo<P0..Pn>() -> impl Trait
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type Foo<P0...Pn>
|
||||
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
|
||||
//
|
||||
// For lifetime parameters we convert
|
||||
//
|
||||
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
|
||||
//
|
||||
// into
|
||||
//
|
||||
// type foo::<'p0..'pn>::Foo<'q0..'qm>
|
||||
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
|
||||
//
|
||||
// which would error here on all of the `'static` args.
|
||||
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()),
|
||||
// Check these
|
||||
OpaqueTyOrigin::TyAlias { .. } => {}
|
||||
}
|
||||
let is_ty_alias = match opaque_ty_hir.expect_opaque_ty().origin {
|
||||
OpaqueTyOrigin::TyAlias { .. } => true,
|
||||
OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false,
|
||||
};
|
||||
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
||||
for (i, arg) in opaque_type_key.args.iter().enumerate() {
|
||||
if let Err(guar) = arg.error_reported() {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
if is_ty_alias {
|
||||
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
|
||||
} else {
|
||||
// FIXME(#113916): we can't currently check for unique lifetime params,
|
||||
// see that issue for more. We will also have to ignore bivariant lifetime
|
||||
// params for RPIT, but that's comparatively trivial ✨
|
||||
continue;
|
||||
}
|
||||
}
|
||||
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
let f = || {
|
||||
let i: u32 = test::<i32>(-1, false);
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
//~| ERROR expected generic type parameter, found `i32`
|
||||
println!("{i}");
|
||||
};
|
||||
if recurse {
|
||||
|
@ -1,3 +1,12 @@
|
||||
error[E0792]: expected generic type parameter, found `i32`
|
||||
--> $DIR/issue-99073-2.rs:9:22
|
||||
|
|
||||
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let f = || {
|
||||
LL | let i: u32 = test::<i32>(-1, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/issue-99073-2.rs:9:22
|
||||
|
|
||||
@ -5,10 +14,11 @@ LL | let i: u32 = test::<i32>(-1, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/issue-99073-2.rs:16:5
|
||||
--> $DIR/issue-99073-2.rs:7:45
|
||||
|
|
||||
LL | t
|
||||
| ^
|
||||
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
@ -5,4 +5,5 @@ fn main() {
|
||||
fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
move || f(fix(&f))
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
//~| ERROR expected generic type parameter, found `&F`
|
||||
}
|
||||
|
@ -1,14 +1,23 @@
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
error[E0792]: expected generic type parameter, found `&F`
|
||||
--> $DIR/issue-99073.rs:6:11
|
||||
|
|
||||
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | move || f(fix(&f))
|
||||
| ^^^^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G`
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/issue-99073.rs:6:13
|
||||
|
|
||||
LL | move || f(fix(&f))
|
||||
| ^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/issue-99073.rs:6:3
|
||||
--> $DIR/issue-99073.rs:5:36
|
||||
|
|
||||
LL | move || f(fix(&f))
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
19
tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs
Normal file
19
tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// check-pass
|
||||
|
||||
// related to #113916, check that using RPITs in functions with lifetime params
|
||||
// which are constrained to be equal compiles.
|
||||
|
||||
trait Trait<'a, 'b> {}
|
||||
impl Trait<'_, '_> for () {}
|
||||
fn pass<'a: 'b, 'b: 'a>() -> impl Trait<'a, 'b> {
|
||||
(|| {})()
|
||||
}
|
||||
|
||||
struct Foo<'a>(&'a ());
|
||||
impl<'a> Foo<'a> {
|
||||
fn bar<'b: 'a>(&'b self) -> impl Trait<'a, 'b> {
|
||||
let _: &'a &'b &'a ();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/impl-trait/rpit/non-defining-use.rs
Normal file
14
tests/ui/impl-trait/rpit/non-defining-use.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// Regression test for #111935 that non-defining uses of RPIT result in errors
|
||||
#![allow(unconditional_recursion)]
|
||||
fn foo<T>() -> impl Sized {
|
||||
let _: () = foo::<u8>(); //~ ERROR expected generic type parameter, found `u8`
|
||||
}
|
||||
|
||||
fn bar<T>(val: T) -> impl Sized {
|
||||
let _: u8 = bar(0u8);
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
//~| ERROR expected generic type parameter, found `u8`
|
||||
val
|
||||
}
|
||||
|
||||
fn main() {}
|
31
tests/ui/impl-trait/rpit/non-defining-use.stderr
Normal file
31
tests/ui/impl-trait/rpit/non-defining-use.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error[E0792]: expected generic type parameter, found `u8`
|
||||
--> $DIR/non-defining-use.rs:4:12
|
||||
|
|
||||
LL | fn foo<T>() -> impl Sized {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let _: () = foo::<u8>();
|
||||
| ^^
|
||||
|
||||
error[E0792]: expected generic type parameter, found `u8`
|
||||
--> $DIR/non-defining-use.rs:8:12
|
||||
|
|
||||
LL | fn bar<T>(val: T) -> impl Sized {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
LL | let _: u8 = bar(0u8);
|
||||
| ^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/non-defining-use.rs:8:17
|
||||
|
|
||||
LL | let _: u8 = bar(0u8);
|
||||
| ^^^^^^^^ expected `T`, got `u8`
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/non-defining-use.rs:7:22
|
||||
|
|
||||
LL | fn bar<T>(val: T) -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
Loading…
Reference in New Issue
Block a user