Skip to content

Commit

Permalink
Rollup merge of rust-lang#109240 - compiler-errors:dont-binder-twice,…
Browse files Browse the repository at this point in the history
… r=oli-obk

Walk un-shifted nested `impl Trait` in trait when setting up default trait method assumptions

Fixes a double subtraction in some binder math in return-position `impl Trait` in trait handling code.

Fixes rust-lang#109239
  • Loading branch information
Nilstrieb committed Mar 21, 2023
2 parents d3749f0 + 239ec6c commit 38e6c35
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 30 deletions.
15 changes: 1 addition & 14 deletions compiler/rustc_middle/src/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ where
// Region folder

impl<'tcx> TyCtxt<'tcx> {
/// Folds the escaping and free regions in `value` using `f`, and
/// sets `skipped_regions` to true if any late-bound region was found
/// and skipped.
/// Folds the escaping and free regions in `value` using `f`.
pub fn fold_regions<T>(
self,
value: T,
Expand All @@ -64,17 +62,6 @@ impl<'tcx> TyCtxt<'tcx> {
{
value.fold_with(&mut RegionFolder::new(self, &mut f))
}

pub fn super_fold_regions<T>(
self,
value: T,
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
T: TypeSuperFoldable<TyCtxt<'tcx>>,
{
value.super_fold_with(&mut RegionFolder::new(self, &mut f))
}
}

/// Folds over the substructure of a type, visiting its component
Expand Down
42 changes: 26 additions & 16 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use rustc_middle::ty::{
TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_session::config::TraitSolver;
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
use rustc_span::{
def_id::{DefId, CRATE_DEF_ID},
DUMMY_SP,
};
use rustc_trait_selection::traits;

fn sized_constraint_for_ty<'tcx>(
Expand Down Expand Up @@ -275,16 +278,22 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
}

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.is_impl_trait_in_trait(alias_ty.def_id)
&& self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id
&& self.seen.insert(alias_ty.def_id)
if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind()
&& self.tcx.is_impl_trait_in_trait(unshifted_alias_ty.def_id)
&& self.tcx.impl_trait_in_trait_parent_fn(unshifted_alias_ty.def_id) == self.fn_def_id
&& self.seen.insert(unshifted_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, _| {
let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
if let ty::ReLateBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
return self.tcx.mk_re_error_with_message(
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
}
self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
} else {
re
Expand All @@ -295,26 +304,27 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
// the `type_of` of the trait's associated item. If we're using the old lowering
// strategy, then just reinterpret the associated type like an opaque :^)
let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
self
.tcx
.type_of(alias_ty.def_id)
.subst(self.tcx, alias_ty.substs)
self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs)
} else {
self.tcx.mk_alias(ty::Opaque, alias_ty)
self.tcx.mk_alias(ty::Opaque, shifted_alias_ty)
};

self.predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_ty: alias_ty,
term: default_ty.into(),
},
ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() },
self.bound_vars,
)
.to_predicate(self.tcx),
);

for bound in self.tcx.item_bounds(alias_ty.def_id).subst_iter(self.tcx, alias_ty.substs)
// We walk the *un-shifted* alias ty, because we're tracking the de bruijn
// binder depth, and if we were to walk `shifted_alias_ty` instead, we'd
// have to reset `self.depth` back to `ty::INNERMOST` or something. It's
// easier to just do this.
for bound in self
.tcx
.item_bounds(unshifted_alias_ty.def_id)
.subst_iter(self.tcx, unshifted_alias_ty.substs)
{
bound.visit_with(self);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ trait Trait {
fn method(&self) -> impl Trait<Type = impl Sized + '_>;
}

trait Trait2 {
type Type;

fn method(&self) -> impl Trait2<Type = impl Trait2<Type = impl Sized + '_> + '_>;
}

fn main() {}

0 comments on commit 38e6c35

Please sign in to comment.