Skip to content

Commit

Permalink
Shift vars for default RPITIT methods correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Feb 28, 2023
1 parent 31f858d commit b7e0ca9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
25 changes: 24 additions & 1 deletion compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}

Expand Down Expand Up @@ -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 {
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs
Original file line number Diff line number Diff line change
@@ -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() {}
11 changes: 11 additions & 0 deletions tests/ui/impl-trait/in-trait/default-method-binder-shifting.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b7e0ca9

Please sign in to comment.