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