Skip to content

Commit b7e0ca9

Browse files
Shift vars for default RPITIT methods correctly
1 parent 31f858d commit b7e0ca9

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)