1 //! A folding traversal mechanism for complex data structures that contain type
4 //! This is a modifying traversal. It consumes the data structure, producing a
5 //! (possibly) modified version of it. Both fallible and infallible versions are
6 //! available. The name is potentially confusing, because this traversal is more
7 //! like `Iterator::map` than `Iterator::fold`.
9 //! This traversal has limited flexibility. Only a small number of "types of
10 //! interest" within the complex data structures can receive custom
11 //! modification. These are the ones containing the most important type-related
12 //! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
14 //! There are three groups of traits involved in each traversal.
15 //! - `TypeFoldable`. This is implemented once for many types, including:
16 //! - Types of interest, for which the the methods delegate to the
18 //! - All other types, including generic containers like `Vec` and `Option`.
19 //! It defines a "skeleton" of how they should be folded.
20 //! - `TypeSuperFoldable`. This is implemented only for each type of interest,
21 //! and defines the folding "skeleton" for these types.
22 //! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each
23 //! folder. This defines how types of interest are folded.
25 //! This means each fold is a mixture of (a) generic folding operations, and (b)
26 //! custom fold operations that are specific to the folder.
27 //! - The `TypeFoldable` impls handle most of the traversal, and call into
28 //! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
29 //! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
30 //! impl, because some of the types of interest are recursive and can contain
31 //! other types of interest.
32 //! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
33 //! impl, because each folder might provide custom handling only for some types
34 //! of interest, or only for some variants of each type of interest, and then
35 //! use default traversal for the remaining cases.
37 //! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
38 //! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
40 //! s.fold_with(folder) calls
41 //! - ty.fold_with(folder) calls
42 //! - folder.fold_ty(ty) may call
43 //! - ty.super_fold_with(folder)
44 //! - u.fold_with(folder)
47 use crate::ty::{self, Binder, Ty, TyCtxt, TypeVisitable};
48 use rustc_hir::def_id::DefId;
50 use std::collections::BTreeMap;
52 /// This trait is implemented for every type that can be folded,
53 /// providing the skeleton of the traversal.
55 /// To implement this conveniently, use the derive macro located in
57 pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> {
58 /// The entry point for folding. To fold a value `t` with a folder `f`
59 /// call: `t.try_fold_with(f)`.
61 /// For most types, this just traverses the value, calling `try_fold_with`
62 /// on each field/element.
64 /// For types of interest (such as `Ty`), the implementation of method
65 /// calls a folder method specifically for that type (such as
66 /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
68 fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error>;
70 /// A convenient alternative to `try_fold_with` for use with infallible
71 /// folders. Do not override this method, to ensure coherence with
73 fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
74 self.try_fold_with(folder).into_ok()
78 // This trait is implemented for types of interest.
79 pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> {
80 /// Provides a default fold for a type of interest. This should only be
81 /// called within `TypeFolder` methods, when a non-custom traversal is
82 /// desired for the value of the type of interest passed to that method.
83 /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
84 /// `ty.try_super_fold_with(self)`, but any other folding should be done
85 /// with `xyz.try_fold_with(self)`.
86 fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
89 ) -> Result<Self, F::Error>;
91 /// A convenient alternative to `try_super_fold_with` for use with
92 /// infallible folders. Do not override this method, to ensure coherence
93 /// with `try_super_fold_with`.
94 fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
95 self.try_super_fold_with(folder).into_ok()
99 /// This trait is implemented for every infallible folding traversal. There is
100 /// a fold method defined for every type of interest. Each such method has a
101 /// default that does an "identity" fold. Implementations of these methods
102 /// often fall back to a `super_fold_with` method if the primary argument
103 /// doesn't satisfy a particular condition.
105 /// A blanket implementation of [`FallibleTypeFolder`] will defer to
106 /// the infallible methods of this trait to ensure that the two APIs
108 pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
109 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
111 fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
113 T: TypeFoldable<'tcx>,
115 t.super_fold_with(self)
118 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
119 t.super_fold_with(self)
122 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
123 r.super_fold_with(self)
126 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
127 c.super_fold_with(self)
130 fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> {
131 uv.super_fold_with(self)
134 fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
135 p.super_fold_with(self)
138 fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
139 bug!("most type folders should not be folding MIR datastructures: {:?}", c)
143 /// This trait is implemented for every folding traversal. There is a fold
144 /// method defined for every type of interest. Each such method has a default
145 /// that does an "identity" fold.
147 /// A blanket implementation of this trait (that defers to the relevant
148 /// method of [`TypeFolder`]) is provided for all infallible folders in
149 /// order to ensure the two APIs are coherent.
150 pub trait FallibleTypeFolder<'tcx>: Sized {
153 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
155 fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
157 T: TypeFoldable<'tcx>,
159 t.try_super_fold_with(self)
162 fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
163 t.try_super_fold_with(self)
166 fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
167 r.try_super_fold_with(self)
170 fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
171 c.try_super_fold_with(self)
174 fn try_fold_unevaluated(
176 c: ty::Unevaluated<'tcx>,
177 ) -> Result<ty::Unevaluated<'tcx>, Self::Error> {
178 c.try_super_fold_with(self)
181 fn try_fold_predicate(
183 p: ty::Predicate<'tcx>,
184 ) -> Result<ty::Predicate<'tcx>, Self::Error> {
185 p.try_super_fold_with(self)
188 fn try_fold_mir_const(
190 c: mir::ConstantKind<'tcx>,
191 ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
192 bug!("most type folders should not be folding MIR datastructures: {:?}", c)
196 // This blanket implementation of the fallible trait for infallible folders
197 // delegates to infallible methods to ensure coherence.
198 impl<'tcx, F> FallibleTypeFolder<'tcx> for F
204 fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
205 TypeFolder::tcx(self)
208 fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, !>
210 T: TypeFoldable<'tcx>,
212 Ok(self.fold_binder(t))
215 fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, !> {
219 fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, !> {
220 Ok(self.fold_region(r))
223 fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, !> {
224 Ok(self.fold_const(c))
227 fn try_fold_unevaluated(
229 c: ty::Unevaluated<'tcx>,
230 ) -> Result<ty::Unevaluated<'tcx>, !> {
231 Ok(self.fold_unevaluated(c))
234 fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
235 Ok(self.fold_predicate(p))
238 fn try_fold_mir_const(
240 c: mir::ConstantKind<'tcx>,
241 ) -> Result<mir::ConstantKind<'tcx>, !> {
242 Ok(self.fold_mir_const(c))
246 ///////////////////////////////////////////////////////////////////////////
247 // Some sample folders
249 pub struct BottomUpFolder<'tcx, F, G, H>
251 F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
252 G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
253 H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
255 pub tcx: TyCtxt<'tcx>,
261 impl<'tcx, F, G, H> TypeFolder<'tcx> for BottomUpFolder<'tcx, F, G, H>
263 F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
264 G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
265 H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
267 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
271 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
272 let t = ty.super_fold_with(self);
276 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
277 let r = r.super_fold_with(self);
281 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
282 let ct = ct.super_fold_with(self);
287 ///////////////////////////////////////////////////////////////////////////
290 impl<'tcx> TyCtxt<'tcx> {
291 /// Folds the escaping and free regions in `value` using `f`, and
292 /// sets `skipped_regions` to true if any late-bound region was found
294 pub fn fold_regions<T>(
297 mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
300 T: TypeFoldable<'tcx>,
302 value.fold_with(&mut RegionFolder::new(self, &mut f))
306 /// Folds over the substructure of a type, visiting its component
307 /// types and all regions that occur *free* within it.
309 /// That is, `Ty` can contain function or method types that bind
310 /// regions at the call site (`ReLateBound`), and occurrences of
311 /// regions (aka "lifetimes") that are bound within a type are not
312 /// visited by this folder; only regions that occur free will be
313 /// visited by `fld_r`.
315 pub struct RegionFolder<'a, 'tcx> {
318 /// Stores the index of a binder *just outside* the stuff we have
319 /// visited. So this begins as INNERMOST; when we pass through a
320 /// binder, it is incremented (via `shift_in`).
321 current_index: ty::DebruijnIndex,
323 /// Callback invokes for each free region. The `DebruijnIndex`
324 /// points to the binder *just outside* the ones we have passed
327 &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a),
330 impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
334 fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
335 ) -> RegionFolder<'a, 'tcx> {
336 RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn }
340 impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
341 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
345 fn fold_binder<T: TypeFoldable<'tcx>>(
347 t: ty::Binder<'tcx, T>,
348 ) -> ty::Binder<'tcx, T> {
349 self.current_index.shift_in(1);
350 let t = t.super_fold_with(self);
351 self.current_index.shift_out(1);
355 #[instrument(skip(self), level = "debug")]
356 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
358 ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
359 debug!(?self.current_index, "skipped bound region");
363 debug!(?self.current_index, "folding free region");
364 (self.fold_region_fn)(r, self.current_index)
370 ///////////////////////////////////////////////////////////////////////////
371 // Bound vars replacer
373 /// Replaces the escaping bound vars (late bound regions or bound types) in a type.
374 struct BoundVarReplacer<'a, 'tcx> {
377 /// As with `RegionFolder`, represents the index of a binder *just outside*
378 /// the ones we have visited.
379 current_index: ty::DebruijnIndex,
381 fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
382 fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
383 fld_c: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a),
386 impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> {
389 fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
390 fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
391 fld_c: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a),
393 BoundVarReplacer { tcx, current_index: ty::INNERMOST, fld_r, fld_t, fld_c }
397 impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
398 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
402 fn fold_binder<T: TypeFoldable<'tcx>>(
404 t: ty::Binder<'tcx, T>,
405 ) -> ty::Binder<'tcx, T> {
406 self.current_index.shift_in(1);
407 let t = t.super_fold_with(self);
408 self.current_index.shift_out(1);
412 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
414 ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
415 let ty = (self.fld_t)(bound_ty);
416 ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32())
418 _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
423 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
425 ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
426 let region = (self.fld_r)(br);
427 if let ty::ReLateBound(debruijn1, br) = *region {
428 // If the callback returns a late-bound region,
429 // that region should always use the INNERMOST
430 // debruijn index. Then we adjust it to the
432 assert_eq!(debruijn1, ty::INNERMOST);
433 self.tcx.mk_region(ty::ReLateBound(debruijn, br))
442 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
444 ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
445 let ct = (self.fld_c)(bound_const, ct.ty());
446 ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
448 _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
454 impl<'tcx> TyCtxt<'tcx> {
455 /// Replaces all regions bound by the given `Binder` with the
456 /// results returned by the closure; the closure is expected to
457 /// return a free region (relative to this binder), and hence the
458 /// binder is removed in the return type. The closure is invoked
459 /// once for each unique `BoundRegionKind`; multiple references to the
460 /// same `BoundRegionKind` will reuse the previous result. A map is
461 /// returned at the end with each bound region and the free region
462 /// that replaced it.
466 /// This method only replaces late bound regions. Any types or
467 /// constants bound by `value` will cause an ICE.
468 pub fn replace_late_bound_regions<T, F>(
470 value: Binder<'tcx, T>,
472 ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
474 F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
475 T: TypeFoldable<'tcx>,
477 let mut region_map = BTreeMap::new();
478 let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
479 let value = self.replace_late_bound_regions_uncached(value, real_fld_r);
483 pub fn replace_late_bound_regions_uncached<T, F>(
485 value: Binder<'tcx, T>,
489 F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
490 T: TypeFoldable<'tcx>,
492 let mut fld_t = |b| bug!("unexpected bound ty in binder: {b:?}");
493 let mut fld_c = |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}");
494 let value = value.skip_binder();
495 if !value.has_escaping_bound_vars() {
498 let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t, &mut fld_c);
499 value.fold_with(&mut replacer)
503 /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
504 /// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c`
505 /// closure replaces escaping bound consts.
506 pub fn replace_escaping_bound_vars_uncached<T, F, G, H>(
514 F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
515 G: FnMut(ty::BoundTy) -> Ty<'tcx>,
516 H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>,
517 T: TypeFoldable<'tcx>,
519 if !value.has_escaping_bound_vars() {
522 let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t, &mut fld_c);
523 value.fold_with(&mut replacer)
527 /// Replaces all types or regions bound by the given `Binder`. The `fld_r`
528 /// closure replaces bound regions, the `fld_t` closure replaces bound
529 /// types, and `fld_c` replaces bound constants.
530 pub fn replace_bound_vars_uncached<T, F, G, H>(
532 value: Binder<'tcx, T>,
538 F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
539 G: FnMut(ty::BoundTy) -> Ty<'tcx>,
540 H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>,
541 T: TypeFoldable<'tcx>,
543 self.replace_escaping_bound_vars_uncached(value.skip_binder(), fld_r, fld_t, fld_c)
546 /// Replaces any late-bound regions bound in `value` with
547 /// free variants attached to `all_outlive_scope`.
548 pub fn liberate_late_bound_regions<T>(
550 all_outlive_scope: DefId,
551 value: ty::Binder<'tcx, T>,
554 T: TypeFoldable<'tcx>,
556 self.replace_late_bound_regions_uncached(value, |br| {
557 self.mk_region(ty::ReFree(ty::FreeRegion {
558 scope: all_outlive_scope,
559 bound_region: br.kind,
564 pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
566 T: TypeFoldable<'tcx>,
568 self.replace_escaping_bound_vars_uncached(
571 self.mk_region(ty::ReLateBound(
574 var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars),
580 self.mk_ty(ty::Bound(
583 var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars),
589 self.mk_const(ty::ConstS {
590 kind: ty::ConstKind::Bound(
592 ty::BoundVar::from_usize(c.as_usize() + bound_vars),
600 /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
601 /// method lookup and a few other places where precise region relationships are not required.
602 pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
604 T: TypeFoldable<'tcx>,
606 self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
609 /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
610 /// assigned starting at 0 and increasing monotonically in the order traversed
611 /// by the fold operation.
613 /// The chief purpose of this function is to canonicalize regions so that two
614 /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
615 /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
616 /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
617 pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T>
619 T: TypeFoldable<'tcx>,
623 .replace_late_bound_regions(sig, |_| {
624 let br = ty::BoundRegion {
625 var: ty::BoundVar::from_u32(counter),
626 kind: ty::BrAnon(counter),
628 let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
633 let bound_vars = self.mk_bound_variable_kinds(
634 (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
636 Binder::bind_with_vars(inner, bound_vars)
640 ///////////////////////////////////////////////////////////////////////////
643 // Shifts the De Bruijn indices on all escaping bound vars by a
644 // fixed amount. Useful in substitution or when otherwise introducing
645 // a binding level that is not intended to capture the existing bound
646 // vars. See comment on `shift_vars_through_binders` method in
647 // `subst.rs` for more details.
649 struct Shifter<'tcx> {
651 current_index: ty::DebruijnIndex,
655 impl<'tcx> Shifter<'tcx> {
656 pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self {
657 Shifter { tcx, current_index: ty::INNERMOST, amount }
661 impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
662 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
666 fn fold_binder<T: TypeFoldable<'tcx>>(
668 t: ty::Binder<'tcx, T>,
669 ) -> ty::Binder<'tcx, T> {
670 self.current_index.shift_in(1);
671 let t = t.super_fold_with(self);
672 self.current_index.shift_out(1);
676 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
678 ty::ReLateBound(debruijn, br) => {
679 if self.amount == 0 || debruijn < self.current_index {
682 let debruijn = debruijn.shifted_in(self.amount);
683 let shifted = ty::ReLateBound(debruijn, br);
684 self.tcx.mk_region(shifted)
691 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
693 ty::Bound(debruijn, bound_ty) => {
694 if self.amount == 0 || debruijn < self.current_index {
697 let debruijn = debruijn.shifted_in(self.amount);
698 self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
702 _ => ty.super_fold_with(self),
706 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
707 if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() {
708 if self.amount == 0 || debruijn < self.current_index {
711 let debruijn = debruijn.shifted_in(self.amount);
712 self.tcx.mk_const(ty::ConstS {
713 kind: ty::ConstKind::Bound(debruijn, bound_ct),
718 ct.super_fold_with(self)
723 pub fn shift_region<'tcx>(
725 region: ty::Region<'tcx>,
727 ) -> ty::Region<'tcx> {
729 ty::ReLateBound(debruijn, br) if amount > 0 => {
730 tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
736 pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
738 T: TypeFoldable<'tcx>,
740 debug!("shift_vars(value={:?}, amount={})", value, amount);
742 value.fold_with(&mut Shifter::new(tcx, amount))