diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 18159778a8e39..70c9de91fbfef 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -142,12 +142,14 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer { 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, fn_def_id: def_id, bound_vars: sig.bound_vars(), predicates: &mut predicates, seen: FxHashSet::default(), + depth: ty::INNERMOST, }); } @@ -244,15 +246,36 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { fn_def_id: DefId, bound_vars: &'tcx ty::List, seen: FxHashSet, + depth: ty::DebruijnIndex, } impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { + fn visit_binder>>( + &mut self, + binder: &ty::Binder<'tcx, T>, + ) -> std::ops::ControlFlow { + 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 { if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() && 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.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( ty::Binder::bind_with_vars( ty::ProjectionPredicate { diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs new file mode 100644 index 0000000000000..5cf90c5d93c24 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs @@ -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; +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.stderr b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.stderr new file mode 100644 index 0000000000000..7c7ebcdb7e717 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.stderr @@ -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 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted +