diff options
| author | Michael Goulet <michael@errs.io> | 2023-02-28 21:34:04 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-02-28 21:34:59 +0000 |
| commit | b7e0ca993d0d1d15ed211ceec53ee4ffe526cb16 (patch) | |
| tree | f9942e95ca65d9eba37f5f06be2506d48a966674 | |
| parent | 31f858d9a511f24fedb8ed997b28304fec809630 (diff) | |
| download | rust-b7e0ca993d0d1d15ed211ceec53ee4ffe526cb16.tar.gz rust-b7e0ca993d0d1d15ed211ceec53ee4ffe526cb16.zip | |
Shift vars for default RPITIT methods correctly
| -rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 25 | ||||
| -rw-r--r-- | tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs | 14 | ||||
| -rw-r--r-- | tests/ui/impl-trait/in-trait/default-method-binder-shifting.stderr | 11 |
3 files changed, 49 insertions, 1 deletions
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 18159778a8e..70c9de91fbf 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<ty::BoundVariableKind>, seen: FxHashSet<DefId>, + depth: ty::DebruijnIndex, } 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> { 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 00000000000..5cf90c5d93c --- /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<Type = impl Sized + '_>; +} + +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 00000000000..7c7ebcdb7e7 --- /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 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + |
