Rollup merge of #109545 - compiler-errors:rpitit-wf, r=eholk

Deeply check well-formedness of return-position `impl Trait` in trait

Walk the bounds of RPITITs to see if we find any more RPITITs 😸
This commit is contained in:
Matthias Krüger 2023-03-25 03:37:12 +01:00 committed by GitHub
commit 3b49ad3814
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 44 deletions

View File

@ -1544,42 +1544,81 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
span: Span, span: Span,
) { ) {
let tcx = wfcx.tcx(); let tcx = wfcx.tcx();
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
&& assoc_item.container == ty::AssocItemContainer::TraitContainer return;
{ };
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering if assoc_item.container != ty::AssocItemContainer::TraitContainer {
// strategy, we can't just call `check_associated_item` on the new RPITITs, return;
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail. }
// That's because we need to check that the bounds of the RPITIT hold using fn_output.visit_with(&mut ImplTraitInTraitFinder {
// the special substs that we create during opaque type lowering, otherwise we're wfcx,
// getting a bunch of early bound and free regions mixed up... Haven't looked too fn_def_id,
// deep into this, though. depth: ty::INNERMOST,
for arg in fn_output.walk() { seen: FxHashSet::default(),
if let ty::GenericArgKind::Type(ty) = arg.unpack() });
// RPITITs are always eagerly normalized into opaques, so always look for an }
// opaque here.
&& let ty::Alias(ty::Opaque, opaque_ty) = ty.kind() // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
&& let Some(opaque_def_id) = opaque_ty.def_id.as_local() // strategy, we can't just call `check_associated_item` on the new RPITITs,
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty() // because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin // That's because we need to check that the bounds of the RPITIT hold using
&& source == fn_def_id // the special substs that we create during opaque type lowering, otherwise we're
// getting a bunch of early bound and free regions mixed up... Haven't looked too
// deep into this, though.
struct ImplTraitInTraitFinder<'a, 'tcx> {
wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
fn_def_id: LocalDefId,
depth: ty::DebruijnIndex,
seen: FxHashSet<DefId>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
type BreakTy = !;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
let tcx = self.wfcx.tcx();
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
&& self.seen.insert(unshifted_opaque_ty.def_id)
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
if let ty::ReLateBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
return tcx.mk_re_error_with_message(
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
}
tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
} else {
re
}
});
for (bound, bound_span) in tcx
.bound_explicit_item_bounds(opaque_ty.def_id)
.subst_iter_copied(tcx, opaque_ty.substs)
{ {
let span = tcx.def_span(opaque_ty.def_id); let bound = self.wfcx.normalize(bound_span, None, bound);
let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id); self.wfcx.register_obligations(traits::wf::predicate_obligations(
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { self.wfcx.infcx,
let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs); self.wfcx.param_env,
let normalized_bound = wfcx.normalize(span, None, bound); self.wfcx.body_def_id,
traits::wf::predicate_obligations( bound,
wfcx.infcx, bound_span,
wfcx.param_env, ));
wfcx.body_def_id, // Set the debruijn index back to innermost here, since we already eagerly
normalized_bound, // shifted the substs that we use to generate these bounds. This is unfortunately
bound_span, // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
) // but that function doesn't actually need to normalize the bound it's visiting
}); // (whereas we have to do so here)...
wfcx.register_obligations(wf_obligations); let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
bound.visit_with(self);
self.depth = old_depth;
} }
} }
ty.super_visit_with(self)
} }
} }

View File

@ -1,5 +1,5 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:11:22 --> $DIR/wf-bounds.rs:13:22
| |
LL | fn nya() -> impl Wf<Vec<[u8]>>; LL | fn nya() -> impl Wf<Vec<[u8]>>;
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -9,7 +9,7 @@ note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:14:23 --> $DIR/wf-bounds.rs:16:23
| |
LL | fn nya2() -> impl Wf<[u8]>; LL | fn nya2() -> impl Wf<[u8]>;
| ^^^^^^^^ doesn't have a size known at compile-time | ^^^^^^^^ doesn't have a size known at compile-time
@ -18,13 +18,23 @@ LL | fn nya2() -> impl Wf<[u8]>;
note: required by a bound in `Wf` note: required by a bound in `Wf`
--> $DIR/wf-bounds.rs:8:10 --> $DIR/wf-bounds.rs:8:10
| |
LL | trait Wf<T> {} LL | trait Wf<T> {
| ^ required by this bound in `Wf` | ^ required by this bound in `Wf`
help: consider relaxing the implicit `Sized` restriction help: consider relaxing the implicit `Sized` restriction
| |
LL | trait Wf<T: ?Sized> {} LL | trait Wf<T: ?Sized> {
| ++++++++ | ++++++++
error: aborting due to 2 previous errors error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:19:44
|
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View File

@ -1,5 +1,5 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:11:22 --> $DIR/wf-bounds.rs:13:22
| |
LL | fn nya() -> impl Wf<Vec<[u8]>>; LL | fn nya() -> impl Wf<Vec<[u8]>>;
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -9,7 +9,7 @@ note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:14:23 --> $DIR/wf-bounds.rs:16:23
| |
LL | fn nya2() -> impl Wf<[u8]>; LL | fn nya2() -> impl Wf<[u8]>;
| ^^^^^^^^ doesn't have a size known at compile-time | ^^^^^^^^ doesn't have a size known at compile-time
@ -18,13 +18,23 @@ LL | fn nya2() -> impl Wf<[u8]>;
note: required by a bound in `Wf` note: required by a bound in `Wf`
--> $DIR/wf-bounds.rs:8:10 --> $DIR/wf-bounds.rs:8:10
| |
LL | trait Wf<T> {} LL | trait Wf<T> {
| ^ required by this bound in `Wf` | ^ required by this bound in `Wf`
help: consider relaxing the implicit `Sized` restriction help: consider relaxing the implicit `Sized` restriction
| |
LL | trait Wf<T: ?Sized> {} LL | trait Wf<T: ?Sized> {
| ++++++++ | ++++++++
error: aborting due to 2 previous errors error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:19:44
|
LL | fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View File

@ -5,7 +5,9 @@
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
trait Wf<T> {} trait Wf<T> {
type Output;
}
trait Uwu { trait Uwu {
fn nya() -> impl Wf<Vec<[u8]>>; fn nya() -> impl Wf<Vec<[u8]>>;
@ -13,6 +15,9 @@ trait Uwu {
fn nya2() -> impl Wf<[u8]>; fn nya2() -> impl Wf<[u8]>;
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
} }
fn main() {} fn main() {}