Rollup merge of #108583 - compiler-errors:rpitit-default-method-with-nested-rpitits, r=spastorino

Account for binders correctly when adding default RPITIT method assumption

As of #108203, we install extra projection predicates into the param-env of a default trait method when it has return-position `impl Trait` (or is async).

The implementation didn't account for the fact that it's walking into and out of binders, so we just need to shift all the debruijn indices accordingly when constructing the projection predicates.

Fixes #108579

r? types
This commit is contained in:
Matthias Krüger 2023-03-07 19:57:44 +01:00 committed by GitHub
commit 63635880f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 1 deletions

View File

@ -142,12 +142,14 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
&& tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
{ {
let sig = tcx.fn_sig(def_id).subst_identity(); let sig = tcx.fn_sig(def_id).subst_identity();
sig.visit_with(&mut ImplTraitInTraitFinder { // We accounted for the binder of the fn sig, so skip the binder.
sig.skip_binder().visit_with(&mut ImplTraitInTraitFinder {
tcx, tcx,
fn_def_id: def_id, fn_def_id: def_id,
bound_vars: sig.bound_vars(), bound_vars: sig.bound_vars(),
predicates: &mut predicates, predicates: &mut predicates,
seen: FxHashSet::default(), seen: FxHashSet::default(),
depth: ty::INNERMOST,
}); });
} }
@ -244,15 +246,36 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
fn_def_id: DefId, fn_def_id: DefId,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>, bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
seen: FxHashSet<DefId>, seen: FxHashSet<DefId>,
depth: ty::DebruijnIndex,
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
binder: &ty::Binder<'tcx, T>,
) -> std::ops::ControlFlow<Self::BreakTy> {
self.depth.shift_in(1);
let binder = binder.super_visit_with(self);
self.depth.shift_out(1);
binder
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
&& self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder && self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
&& self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id && self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
&& self.seen.insert(alias_ty.def_id) && self.seen.insert(alias_ty.def_id)
{ {
// We have entered some binders as we've walked into the
// bounds of the RPITIT. Shift these binders back out when
// constructing the top-level projection predicate.
let alias_ty = self.tcx.fold_regions(alias_ty, |re, _| {
if let ty::ReLateBound(index, bv) = re.kind() {
self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
} else {
re
}
});
self.predicates.push( self.predicates.push(
ty::Binder::bind_with_vars( ty::Binder::bind_with_vars(
ty::ProjectionPredicate { ty::ProjectionPredicate {

View File

@ -0,0 +1,14 @@
// check-pass
#![feature(return_position_impl_trait_in_trait)]
//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
trait Trait {
type Type;
// Check that we're adjusting bound vars correctly when installing the default
// method projection assumptions.
fn method(&self) -> impl Trait<Type = impl Sized + '_>;
}
fn main() {}

View File

@ -0,0 +1,11 @@
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/default-method-binder-shifting.rs:3:12
|
LL | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted