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
|
&& tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
|
||||||
{
|
{
|
||||||
let sig = tcx.fn_sig(def_id).subst_identity();
|
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,
|
tcx,
|
||||||
fn_def_id: def_id,
|
fn_def_id: def_id,
|
||||||
bound_vars: sig.bound_vars(),
|
bound_vars: sig.bound_vars(),
|
||||||
predicates: &mut predicates,
|
predicates: &mut predicates,
|
||||||
seen: FxHashSet::default(),
|
seen: FxHashSet::default(),
|
||||||
|
depth: ty::INNERMOST,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,15 +246,36 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
|
|||||||
fn_def_id: DefId,
|
fn_def_id: DefId,
|
||||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||||
seen: FxHashSet<DefId>,
|
seen: FxHashSet<DefId>,
|
||||||
|
depth: ty::DebruijnIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
|
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> {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
|
||||||
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
|
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
|
||||||
&& self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
|
&& 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.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
|
||||||
&& self.seen.insert(alias_ty.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(
|
self.predicates.push(
|
||||||
ty::Binder::bind_with_vars(
|
ty::Binder::bind_with_vars(
|
||||||
ty::ProjectionPredicate {
|
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