]>
Commit | Line | Data |
---|---|---|
9ffffee4 | 1 | use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt}; |
064997fb | 2 | use rustc_data_structures::fx::FxIndexMap; |
dfeec247 | 3 | use rustc_hir::def_id::DefId; |
e9174d1e | 4 | |
94b46f34 | 5 | use std::collections::BTreeMap; |
e9174d1e | 6 | |
9ffffee4 | 7 | pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; |
a2a8927a | 8 | |
e9174d1e SL |
9 | /////////////////////////////////////////////////////////////////////////// |
10 | // Some sample folders | |
11 | ||
dc9dc135 XL |
12 | pub struct BottomUpFolder<'tcx, F, G, H> |
13 | where | |
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 | 24 | impl<'tcx, F, G, H> TypeFolder<TyCtxt<'tcx>> for BottomUpFolder<'tcx, F, G, H> |
dc9dc135 XL |
25 | where |
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 | 54 | impl<'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 |
77 | pub 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 | 92 | impl<'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 |
102 | impl<'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 |
135 | pub 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 |
141 | pub 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 | |
147 | impl<'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 | 160 | struct 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 |
170 | impl<'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 | 176 | impl<'tcx, D> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'tcx, D> |
064997fb FG |
177 | where |
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 | 241 | impl<'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 |
423 | struct Shifter<'tcx> { |
424 | tcx: TyCtxt<'tcx>, | |
a1dfa0c6 XL |
425 | current_index: ty::DebruijnIndex, |
426 | amount: u32, | |
a1dfa0c6 XL |
427 | } |
428 | ||
a2a8927a | 429 | impl<'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 |
435 | impl<'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 |
488 | pub 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 | 501 | pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T |
dc9dc135 | 502 | where |
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 | } |