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:
commit
3b49ad3814
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
@ -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`.
|
||||||
|
@ -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() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user