]>
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> { | |
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 | 53 | impl<'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 |
76 | pub 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 | 91 | impl<'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 |
101 | impl<'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 |
134 | pub 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 |
140 | pub 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 | |
146 | impl<'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 | 159 | struct 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 |
169 | impl<'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 | 175 | impl<'tcx, D> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'tcx, D> |
064997fb FG |
176 | where |
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 | 240 | impl<'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 |
422 | struct Shifter<'tcx> { |
423 | tcx: TyCtxt<'tcx>, | |
a1dfa0c6 XL |
424 | current_index: ty::DebruijnIndex, |
425 | amount: u32, | |
a1dfa0c6 XL |
426 | } |
427 | ||
a2a8927a | 428 | impl<'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 |
434 | impl<'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 |
487 | pub 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 | 500 | pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T |
dc9dc135 | 501 | where |
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 | } |