]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/fold.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / fold.rs
CommitLineData
9ffffee4 1use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
064997fb 2use rustc_data_structures::fx::FxIndexMap;
dfeec247 3use rustc_hir::def_id::DefId;
e9174d1e 4
94b46f34 5use std::collections::BTreeMap;
e9174d1e 6
9ffffee4 7pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
a2a8927a 8
e9174d1e
SL
9///////////////////////////////////////////////////////////////////////////
10// Some sample folders
11
dc9dc135
XL
12pub struct BottomUpFolder<'tcx, F, G, H>
13where
14 F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
15 G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
5099ac24 16 H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
a7813a04 17{
dc9dc135 18 pub tcx: TyCtxt<'tcx>,
48663c56
XL
19 pub ty_op: F,
20 pub lt_op: G,
21 pub ct_op: H,
e9174d1e
SL
22}
23
9ffffee4 24impl<'tcx, F, G, H> TypeFolder<TyCtxt<'tcx>> for BottomUpFolder<'tcx, F, G, H>
dc9dc135
XL
25where
26 F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
27 G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
5099ac24 28 H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
e9174d1e 29{
9ffffee4 30 fn interner(&self) -> TyCtxt<'tcx> {
dc9dc135 31 self.tcx
dfeec247 32 }
e9174d1e
SL
33
34 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
48663c56
XL
35 let t = ty.super_fold_with(self);
36 (self.ty_op)(t)
e9174d1e 37 }
8faf50e0
XL
38
39 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
49aad941
FG
40 // This one is a little different, because `super_fold_with` is not
41 // implemented on non-recursive `Region`.
48663c56
XL
42 (self.lt_op)(r)
43 }
44
5099ac24 45 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
48663c56
XL
46 let ct = ct.super_fold_with(self);
47 (self.ct_op)(ct)
8faf50e0 48 }
e9174d1e
SL
49}
50
51///////////////////////////////////////////////////////////////////////////
52// Region folder
53
dc9dc135 54impl<'tcx> TyCtxt<'tcx> {
353b0b11 55 /// Folds the escaping and free regions in `value` using `f`.
94b46f34
XL
56 pub fn fold_regions<T>(
57 self,
fc512014 58 value: T,
94b46f34
XL
59 mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
60 ) -> T
61 where
9ffffee4 62 T: TypeFoldable<TyCtxt<'tcx>>,
e9174d1e 63 {
064997fb 64 value.fold_with(&mut RegionFolder::new(self, &mut f))
abe05a73 65 }
e9174d1e
SL
66}
67
68/// Folds over the substructure of a type, visiting its component
69/// types and all regions that occur *free* within it.
70///
71/// That is, `Ty` can contain function or method types that bind
72/// regions at the call site (`ReLateBound`), and occurrences of
73/// regions (aka "lifetimes") that are bound within a type are not
74/// visited by this folder; only regions that occur free will be
75/// visited by `fld_r`.
76
dc9dc135
XL
77pub struct RegionFolder<'a, 'tcx> {
78 tcx: TyCtxt<'tcx>,
94b46f34
XL
79
80 /// Stores the index of a binder *just outside* the stuff we have
9c376795 81 /// visited. So this begins as INNERMOST; when we pass through a
94b46f34
XL
82 /// binder, it is incremented (via `shift_in`).
83 current_index: ty::DebruijnIndex,
84
85 /// Callback invokes for each free region. The `DebruijnIndex`
86 /// points to the binder *just outside* the ones we have passed
87 /// through.
dc9dc135
XL
88 fold_region_fn:
89 &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a),
e9174d1e
SL
90}
91
dc9dc135 92impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
a1dfa0c6 93 #[inline]
94b46f34 94 pub fn new(
dc9dc135 95 tcx: TyCtxt<'tcx>,
94b46f34 96 fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
dc9dc135 97 ) -> RegionFolder<'a, 'tcx> {
064997fb 98 RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn }
e9174d1e
SL
99 }
100}
101
9ffffee4
FG
102impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
103 fn interner(&self) -> TyCtxt<'tcx> {
dc9dc135 104 self.tcx
dfeec247 105 }
e9174d1e 106
9ffffee4 107 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
cdc7bbd5
XL
108 &mut self,
109 t: ty::Binder<'tcx, T>,
110 ) -> ty::Binder<'tcx, T> {
94b46f34 111 self.current_index.shift_in(1);
54a0048b 112 let t = t.super_fold_with(self);
94b46f34 113 self.current_index.shift_out(1);
54a0048b 114 t
e9174d1e
SL
115 }
116
f2b60f7d 117 #[instrument(skip(self), level = "debug", ret)]
7cac9316 118 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
9e0c209e 119 match *r {
94b46f34 120 ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
c295e0f8 121 debug!(?self.current_index, "skipped bound region");
e9174d1e
SL
122 r
123 }
124 _ => {
c295e0f8 125 debug!(?self.current_index, "folding free region");
94b46f34 126 (self.fold_region_fn)(r, self.current_index)
e9174d1e
SL
127 }
128 }
129 }
130}
131
132///////////////////////////////////////////////////////////////////////////
a1dfa0c6 133// Bound vars replacer
e9174d1e 134
064997fb
FG
135pub trait BoundVarReplacerDelegate<'tcx> {
136 fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>;
137 fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>;
138 fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx>;
139}
140
f2b60f7d
FG
141pub struct FnMutDelegate<'a, 'tcx> {
142 pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
143 pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
144 pub consts: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a),
064997fb 145}
f2b60f7d
FG
146
147impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> {
064997fb
FG
148 fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
149 (self.regions)(br)
150 }
151 fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
152 (self.types)(bt)
153 }
154 fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
155 (self.consts)(bv, ty)
156 }
157}
158
a1dfa0c6 159/// Replaces the escaping bound vars (late bound regions or bound types) in a type.
064997fb 160struct BoundVarReplacer<'tcx, D> {
dc9dc135 161 tcx: TyCtxt<'tcx>,
94b46f34
XL
162
163 /// As with `RegionFolder`, represents the index of a binder *just outside*
164 /// the ones we have visited.
165 current_index: ty::DebruijnIndex,
166
064997fb 167 delegate: D,
a1dfa0c6
XL
168}
169
064997fb
FG
170impl<'tcx, D: BoundVarReplacerDelegate<'tcx>> BoundVarReplacer<'tcx, D> {
171 fn new(tcx: TyCtxt<'tcx>, delegate: D) -> Self {
172 BoundVarReplacer { tcx, current_index: ty::INNERMOST, delegate }
a1dfa0c6
XL
173 }
174}
175
9ffffee4 176impl<'tcx, D> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'tcx, D>
064997fb
FG
177where
178 D: BoundVarReplacerDelegate<'tcx>,
179{
9ffffee4 180 fn interner(&self) -> TyCtxt<'tcx> {
dc9dc135 181 self.tcx
dfeec247 182 }
a1dfa0c6 183
9ffffee4 184 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
cdc7bbd5
XL
185 &mut self,
186 t: ty::Binder<'tcx, T>,
187 ) -> ty::Binder<'tcx, T> {
a1dfa0c6
XL
188 self.current_index.shift_in(1);
189 let t = t.super_fold_with(self);
190 self.current_index.shift_out(1);
191 t
192 }
193
194 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1b1a35ee 195 match *t.kind() {
6a06907d 196 ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
064997fb 197 let ty = self.delegate.replace_ty(bound_ty);
487cf647 198 debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST));
923072b8 199 ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32())
a1dfa0c6 200 }
923072b8
FG
201 _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
202 _ => t,
a1dfa0c6
XL
203 }
204 }
205
206 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
207 match *r {
208 ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
064997fb 209 let region = self.delegate.replace_region(br);
923072b8
FG
210 if let ty::ReLateBound(debruijn1, br) = *region {
211 // If the callback returns a late-bound region,
212 // that region should always use the INNERMOST
213 // debruijn index. Then we adjust it to the
214 // correct depth.
215 assert_eq!(debruijn1, ty::INNERMOST);
9ffffee4 216 self.tcx.mk_re_late_bound(debruijn, br)
923072b8
FG
217 } else {
218 region
a1dfa0c6
XL
219 }
220 }
923072b8 221 _ => r,
a1dfa0c6
XL
222 }
223 }
48663c56 224
5099ac24 225 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
923072b8 226 match ct.kind() {
5099ac24 227 ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
064997fb 228 let ct = self.delegate.replace_const(bound_const, ct.ty());
487cf647 229 debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST));
923072b8 230 ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
48663c56 231 }
064997fb 232 _ => ct.super_fold_with(self),
48663c56
XL
233 }
234 }
064997fb
FG
235
236 fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
237 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
238 }
e9174d1e
SL
239}
240
dc9dc135 241impl<'tcx> TyCtxt<'tcx> {
9fa01778 242 /// Replaces all regions bound by the given `Binder` with the
ff7c6d11
XL
243 /// results returned by the closure; the closure is expected to
244 /// return a free region (relative to this binder), and hence the
245 /// binder is removed in the return type. The closure is invoked
fc512014
XL
246 /// once for each unique `BoundRegionKind`; multiple references to the
247 /// same `BoundRegionKind` will reuse the previous result. A map is
ff7c6d11
XL
248 /// returned at the end with each bound region and the free region
249 /// that replaced it.
a1dfa0c6 250 ///
923072b8
FG
251 /// # Panics
252 ///
253 /// This method only replaces late bound regions. Any types or
254 /// constants bound by `value` will cause an ICE.
a1dfa0c6
XL
255 pub fn replace_late_bound_regions<T, F>(
256 self,
cdc7bbd5 257 value: Binder<'tcx, T>,
fc512014 258 mut fld_r: F,
a1dfa0c6 259 ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
dfeec247
XL
260 where
261 F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
9ffffee4 262 T: TypeFoldable<TyCtxt<'tcx>>,
a1dfa0c6 263 {
fc512014 264 let mut region_map = BTreeMap::new();
923072b8
FG
265 let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
266 let value = self.replace_late_bound_regions_uncached(value, real_fld_r);
267 (value, region_map)
268 }
269
270 pub fn replace_late_bound_regions_uncached<T, F>(
271 self,
272 value: Binder<'tcx, T>,
f2b60f7d 273 mut replace_regions: F,
923072b8
FG
274 ) -> T
275 where
276 F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
9ffffee4 277 T: TypeFoldable<TyCtxt<'tcx>>,
923072b8 278 {
6a06907d 279 let value = value.skip_binder();
923072b8 280 if !value.has_escaping_bound_vars() {
6a06907d
XL
281 value
282 } else {
064997fb 283 let delegate = FnMutDelegate {
f2b60f7d
FG
284 regions: &mut replace_regions,
285 types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
286 consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
064997fb
FG
287 };
288 let mut replacer = BoundVarReplacer::new(self, delegate);
6a06907d 289 value.fold_with(&mut replacer)
923072b8 290 }
a1dfa0c6
XL
291 }
292
9fa01778 293 /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
48663c56
XL
294 /// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c`
295 /// closure replaces escaping bound consts.
9ffffee4 296 pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<TyCtxt<'tcx>>>(
a1dfa0c6 297 self,
fc512014 298 value: T,
064997fb
FG
299 delegate: impl BoundVarReplacerDelegate<'tcx>,
300 ) -> T {
a1dfa0c6 301 if !value.has_escaping_bound_vars() {
fc512014 302 value
a1dfa0c6 303 } else {
064997fb 304 let mut replacer = BoundVarReplacer::new(self, delegate);
fc512014 305 value.fold_with(&mut replacer)
a1dfa0c6
XL
306 }
307 }
308
9fa01778 309 /// Replaces all types or regions bound by the given `Binder`. The `fld_r`
923072b8
FG
310 /// closure replaces bound regions, the `fld_t` closure replaces bound
311 /// types, and `fld_c` replaces bound constants.
9ffffee4 312 pub fn replace_bound_vars_uncached<T: TypeFoldable<TyCtxt<'tcx>>>(
a1dfa0c6 313 self,
cdc7bbd5 314 value: Binder<'tcx, T>,
064997fb
FG
315 delegate: impl BoundVarReplacerDelegate<'tcx>,
316 ) -> T {
317 self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)
e9174d1e
SL
318 }
319
9fa01778 320 /// Replaces any late-bound regions bound in `value` with
ff7c6d11 321 /// free variants attached to `all_outlive_scope`.
cdc7bbd5
XL
322 pub fn liberate_late_bound_regions<T>(
323 self,
324 all_outlive_scope: DefId,
325 value: ty::Binder<'tcx, T>,
326 ) -> T
dfeec247 327 where
9ffffee4 328 T: TypeFoldable<TyCtxt<'tcx>>,
dfeec247 329 {
923072b8 330 self.replace_late_bound_regions_uncached(value, |br| {
9ffffee4 331 self.mk_re_free(all_outlive_scope, br.kind)
dfeec247 332 })
ff7c6d11
XL
333 }
334
cdc7bbd5
XL
335 pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
336 where
9ffffee4 337 T: TypeFoldable<TyCtxt<'tcx>>,
cdc7bbd5 338 {
064997fb 339 let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars);
923072b8 340 self.replace_escaping_bound_vars_uncached(
cdc7bbd5 341 value,
064997fb 342 FnMutDelegate {
f2b60f7d 343 regions: &mut |r: ty::BoundRegion| {
9ffffee4 344 self.mk_re_late_bound(
cdc7bbd5 345 ty::INNERMOST,
064997fb 346 ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
9ffffee4 347 )
064997fb 348 },
f2b60f7d 349 types: &mut |t: ty::BoundTy| {
9ffffee4 350 self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
064997fb 351 },
f2b60f7d 352 consts: &mut |c, ty: Ty<'tcx>| {
487cf647 353 self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty)
064997fb 354 },
cdc7bbd5
XL
355 },
356 )
357 }
358
9fa01778 359 /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
e9174d1e 360 /// method lookup and a few other places where precise region relationships are not required.
cdc7bbd5 361 pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
dfeec247 362 where
9ffffee4 363 T: TypeFoldable<TyCtxt<'tcx>>,
e9174d1e 364 {
48663c56 365 self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
e9174d1e
SL
366 }
367
064997fb
FG
368 /// Anonymize all bound variables in `value`, this is mostly used to improve caching.
369 pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T>
370 where
9ffffee4 371 T: TypeFoldable<TyCtxt<'tcx>>,
064997fb
FG
372 {
373 struct Anonymize<'a, 'tcx> {
374 tcx: TyCtxt<'tcx>,
375 map: &'a mut FxIndexMap<ty::BoundVar, ty::BoundVariableKind>,
cdc7bbd5 376 }
064997fb
FG
377 impl<'tcx> BoundVarReplacerDelegate<'tcx> for Anonymize<'_, 'tcx> {
378 fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
379 let entry = self.map.entry(br.var);
380 let index = entry.index();
381 let var = ty::BoundVar::from_usize(index);
382 let kind = entry
353b0b11 383 .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
064997fb
FG
384 .expect_region();
385 let br = ty::BoundRegion { var, kind };
9ffffee4 386 self.tcx.mk_re_late_bound(ty::INNERMOST, br)
cdc7bbd5 387 }
064997fb
FG
388 fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
389 let entry = self.map.entry(bt.var);
390 let index = entry.index();
391 let var = ty::BoundVar::from_usize(index);
392 let kind = entry
353b0b11 393 .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
064997fb 394 .expect_ty();
9ffffee4 395 self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
cdc7bbd5 396 }
064997fb
FG
397 fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
398 let entry = self.map.entry(bv);
399 let index = entry.index();
400 let var = ty::BoundVar::from_usize(index);
401 let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
487cf647 402 self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty)
064997fb
FG
403 }
404 }
cdc7bbd5 405
064997fb
FG
406 let mut map = Default::default();
407 let delegate = Anonymize { tcx: self, map: &mut map };
408 let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
9ffffee4 409 let bound_vars = self.mk_bound_variable_kinds_from_iter(map.into_values());
064997fb 410 Binder::bind_with_vars(inner, bound_vars)
e9174d1e
SL
411 }
412}
413
a1dfa0c6
XL
414///////////////////////////////////////////////////////////////////////////
415// Shifter
416//
417// Shifts the De Bruijn indices on all escaping bound vars by a
418// fixed amount. Useful in substitution or when otherwise introducing
419// a binding level that is not intended to capture the existing bound
420// vars. See comment on `shift_vars_through_binders` method in
421// `subst.rs` for more details.
422
dc9dc135
XL
423struct Shifter<'tcx> {
424 tcx: TyCtxt<'tcx>,
a1dfa0c6
XL
425 current_index: ty::DebruijnIndex,
426 amount: u32,
a1dfa0c6
XL
427}
428
a2a8927a 429impl<'tcx> Shifter<'tcx> {
29967ef6
XL
430 pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self {
431 Shifter { tcx, current_index: ty::INNERMOST, amount }
e9174d1e
SL
432 }
433}
434
9ffffee4
FG
435impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
436 fn interner(&self) -> TyCtxt<'tcx> {
dc9dc135 437 self.tcx
dfeec247 438 }
e9174d1e 439
9ffffee4 440 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
cdc7bbd5
XL
441 &mut self,
442 t: ty::Binder<'tcx, T>,
443 ) -> ty::Binder<'tcx, T> {
94b46f34 444 self.current_index.shift_in(1);
54a0048b 445 let t = t.super_fold_with(self);
94b46f34 446 self.current_index.shift_out(1);
54a0048b 447 t
e9174d1e
SL
448 }
449
7cac9316 450 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
9e0c209e 451 match *r {
487cf647
FG
452 ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
453 let debruijn = debruijn.shifted_in(self.amount);
9ffffee4 454 self.tcx.mk_re_late_bound(debruijn, br)
e9174d1e 455 }
dfeec247 456 _ => r,
e9174d1e
SL
457 }
458 }
e9174d1e 459
48663c56 460 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1b1a35ee 461 match *ty.kind() {
487cf647
FG
462 ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
463 let debruijn = debruijn.shifted_in(self.amount);
9ffffee4 464 self.tcx.mk_bound(debruijn, bound_ty)
a1dfa0c6 465 }
e9174d1e 466
487cf647
FG
467 _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
468 _ => ty,
e9174d1e
SL
469 }
470 }
48663c56 471
5099ac24 472 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
487cf647
FG
473 if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind()
474 && debruijn >= self.current_index
475 {
476 let debruijn = debruijn.shifted_in(self.amount);
477 self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty())
48663c56
XL
478 } else {
479 ct.super_fold_with(self)
480 }
481 }
487cf647
FG
482
483 fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
484 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
485 }
e9174d1e
SL
486}
487
dc9dc135
XL
488pub fn shift_region<'tcx>(
489 tcx: TyCtxt<'tcx>,
7cac9316 490 region: ty::Region<'tcx>,
dc9dc135 491 amount: u32,
a1dfa0c6 492) -> ty::Region<'tcx> {
5099ac24 493 match *region {
a1dfa0c6 494 ty::ReLateBound(debruijn, br) if amount > 0 => {
9ffffee4 495 tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
cc61c64b 496 }
dfeec247 497 _ => region,
cc61c64b
XL
498 }
499}
500
fc512014 501pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
dc9dc135 502where
9ffffee4 503 T: TypeFoldable<TyCtxt<'tcx>>,
dc9dc135 504{
dfeec247 505 debug!("shift_vars(value={:?}, amount={})", value, amount);
a1dfa0c6 506
487cf647
FG
507 if amount == 0 || !value.has_escaping_bound_vars() {
508 return value;
509 }
510
29967ef6 511 value.fold_with(&mut Shifter::new(tcx, amount))
e9174d1e 512}