Skip to content

Commit 6363588

Browse files
authored
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
2 parents 23beda4 + b7e0ca9 commit 6363588

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

compiler/rustc_ty_utils/src/ty.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,14 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
142142
&& tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
143143
{
144144
let sig = tcx.fn_sig(def_id).subst_identity();
145-
sig.visit_with(&mut ImplTraitInTraitFinder {
145+
// We accounted for the binder of the fn sig, so skip the binder.
146+
sig.skip_binder().visit_with(&mut ImplTraitInTraitFinder {
146147
tcx,
147148
fn_def_id: def_id,
148149
bound_vars: sig.bound_vars(),
149150
predicates: &mut predicates,
150151
seen: FxHashSet::default(),
152+
depth: ty::INNERMOST,
151153
});
152154
}
153155

@@ -244,15 +246,36 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
244246
fn_def_id: DefId,
245247
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
246248
seen: FxHashSet<DefId>,
249+
depth: ty::DebruijnIndex,
247250
}
248251

249252
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
253+
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
254+
&mut self,
255+
binder: &ty::Binder<'tcx, T>,
256+
) -> std::ops::ControlFlow<Self::BreakTy> {
257+
self.depth.shift_in(1);
258+
let binder = binder.super_visit_with(self);
259+
self.depth.shift_out(1);
260+
binder
261+
}
262+
250263
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
251264
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
252265
&& self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
253266
&& self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
254267
&& self.seen.insert(alias_ty.def_id)
255268
{
269+
// We have entered some binders as we've walked into the
270+
// bounds of the RPITIT. Shift these binders back out when
271+
// constructing the top-level projection predicate.
272+
let alias_ty = self.tcx.fold_regions(alias_ty, |re, _| {
273+
if let ty::ReLateBound(index, bv) = re.kind() {
274+
self.tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
275+
} else {
276+
re
277+
}
278+
});
256279
self.predicates.push(
257280
ty::Binder::bind_with_vars(
258281
ty::ProjectionPredicate {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
#![feature(return_position_impl_trait_in_trait)]
4+
//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
5+
6+
trait Trait {
7+
type Type;
8+
9+
// Check that we're adjusting bound vars correctly when installing the default
10+
// method projection assumptions.
11+
fn method(&self) -> impl Trait<Type = impl Sized + '_>;
12+
}
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/default-method-binder-shifting.rs:3:12
3+
|
4+
LL | #![feature(return_position_impl_trait_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)