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:
commit
63635880f6
@ -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 {
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user