]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/fold.rs
Add `constness` field to `ty::Predicate::Trait`
[rust.git] / src / librustc / ty / fold.rs
1 //! Generalized type folding mechanism. The setup is a bit convoluted
2 //! but allows for convenient usage. Let T be an instance of some
3 //! "foldable type" (one which implements `TypeFoldable`) and F be an
4 //! instance of a "folder" (a type which implements `TypeFolder`). Then
5 //! the setup is intended to be:
6 //!
7 //!     T.fold_with(F) --calls--> F.fold_T(T) --calls--> T.super_fold_with(F)
8 //!
9 //! This way, when you define a new folder F, you can override
10 //! `fold_T()` to customize the behavior, and invoke `T.super_fold_with()`
11 //! to get the original behavior. Meanwhile, to actually fold
12 //! something, you can just write `T.fold_with(F)`, which is
13 //! convenient. (Note that `fold_with` will also transparently handle
14 //! things like a `Vec<T>` where T is foldable and so on.)
15 //!
16 //! In this ideal setup, the only function that actually *does*
17 //! anything is `T.super_fold_with()`, which traverses the type `T`.
18 //! Moreover, `T.super_fold_with()` should only ever call `T.fold_with()`.
19 //!
20 //! In some cases, we follow a degenerate pattern where we do not have
21 //! a `fold_T` method. Instead, `T.fold_with` traverses the structure directly.
22 //! This is suboptimal because the behavior cannot be overridden, but it's
23 //! much less work to implement. If you ever *do* need an override that
24 //! doesn't exist, it's not hard to convert the degenerate pattern into the
25 //! proper thing.
26 //!
27 //! A `TypeFoldable` T can also be visited by a `TypeVisitor` V using similar setup:
28 //!
29 //!     T.visit_with(V) --calls--> V.visit_T(T) --calls--> T.super_visit_with(V).
30 //!
31 //! These methods return true to indicate that the visitor has found what it is
32 //! looking for, and does not need to visit anything else.
33
34 use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
35 use rustc_hir::def_id::DefId;
36
37 use rustc_data_structures::fx::FxHashSet;
38 use std::collections::BTreeMap;
39 use std::fmt;
40
41 /// This trait is implemented for every type that can be folded.
42 /// Basically, every type that has a corresponding method in `TypeFolder`.
43 ///
44 /// To implement this conveniently, use the derive macro located in librustc_macros.
45 pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
46     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
47     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
48         self.super_fold_with(folder)
49     }
50
51     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool;
52     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
53         self.super_visit_with(visitor)
54     }
55
56     /// Returns `true` if `self` has any late-bound regions that are either
57     /// bound by `binder` or bound by some binder outside of `binder`.
58     /// If `binder` is `ty::INNERMOST`, this indicates whether
59     /// there are any late-bound regions that appear free.
60     fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
61         self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder })
62     }
63
64     /// Returns `true` if this `self` has any regions that escape `binder` (and
65     /// hence are not bound by it).
66     fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
67         self.has_vars_bound_at_or_above(binder.shifted_in(1))
68     }
69
70     fn has_escaping_bound_vars(&self) -> bool {
71         self.has_vars_bound_at_or_above(ty::INNERMOST)
72     }
73
74     fn has_type_flags(&self, flags: TypeFlags) -> bool {
75         self.visit_with(&mut HasTypeFlagsVisitor { flags })
76     }
77     fn has_projections(&self) -> bool {
78         self.has_type_flags(TypeFlags::HAS_PROJECTION)
79     }
80     fn references_error(&self) -> bool {
81         self.has_type_flags(TypeFlags::HAS_TY_ERR)
82     }
83     fn has_param_types(&self) -> bool {
84         self.has_type_flags(TypeFlags::HAS_PARAMS)
85     }
86     fn has_infer_types(&self) -> bool {
87         self.has_type_flags(TypeFlags::HAS_TY_INFER)
88     }
89     fn has_infer_consts(&self) -> bool {
90         self.has_type_flags(TypeFlags::HAS_CT_INFER)
91     }
92     fn has_local_value(&self) -> bool {
93         self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
94     }
95     fn needs_infer(&self) -> bool {
96         self.has_type_flags(
97             TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER,
98         )
99     }
100     fn has_placeholders(&self) -> bool {
101         self.has_type_flags(
102             TypeFlags::HAS_RE_PLACEHOLDER
103                 | TypeFlags::HAS_TY_PLACEHOLDER
104                 | TypeFlags::HAS_CT_PLACEHOLDER,
105         )
106     }
107     fn needs_subst(&self) -> bool {
108         self.has_type_flags(TypeFlags::NEEDS_SUBST)
109     }
110     fn has_re_placeholders(&self) -> bool {
111         self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER)
112     }
113     fn has_closure_types(&self) -> bool {
114         self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
115     }
116     /// "Free" regions in this context means that it has any region
117     /// that is not (a) erased or (b) late-bound.
118     fn has_free_regions(&self) -> bool {
119         self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
120     }
121
122     /// True if there are any un-erased free regions.
123     fn has_erasable_regions(&self) -> bool {
124         self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
125     }
126
127     /// Indicates whether this value references only 'global'
128     /// generic parameters that are the same regardless of what fn we are
129     /// in. This is used for caching.
130     fn is_global(&self) -> bool {
131         !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
132     }
133
134     /// True if there are any late-bound regions
135     fn has_late_bound_regions(&self) -> bool {
136         self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
137     }
138
139     /// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
140     fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
141         pub struct Visitor<F>(F);
142
143         impl<'tcx, F: FnMut(Ty<'tcx>) -> bool> TypeVisitor<'tcx> for Visitor<F> {
144             fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
145                 self.0(ty)
146             }
147         }
148
149         self.visit_with(&mut Visitor(visit))
150     }
151 }
152
153 impl TypeFoldable<'tcx> for syntax::ast::Constness {
154     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
155         *self
156     }
157     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
158         false
159     }
160 }
161
162 /// The `TypeFolder` trait defines the actual *folding*. There is a
163 /// method defined for every foldable type. Each of these has a
164 /// default implementation that does an "identity" fold. Within each
165 /// identity fold, it should invoke `foo.fold_with(self)` to fold each
166 /// sub-item.
167 pub trait TypeFolder<'tcx>: Sized {
168     fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
169
170     fn fold_binder<T>(&mut self, t: &Binder<T>) -> Binder<T>
171     where
172         T: TypeFoldable<'tcx>,
173     {
174         t.super_fold_with(self)
175     }
176
177     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
178         t.super_fold_with(self)
179     }
180
181     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
182         r.super_fold_with(self)
183     }
184
185     fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
186         c.super_fold_with(self)
187     }
188 }
189
190 pub trait TypeVisitor<'tcx>: Sized {
191     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
192         t.super_visit_with(self)
193     }
194
195     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
196         t.super_visit_with(self)
197     }
198
199     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
200         r.super_visit_with(self)
201     }
202
203     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
204         c.super_visit_with(self)
205     }
206 }
207
208 ///////////////////////////////////////////////////////////////////////////
209 // Some sample folders
210
211 pub struct BottomUpFolder<'tcx, F, G, H>
212 where
213     F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
214     G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
215     H: FnMut(&'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx>,
216 {
217     pub tcx: TyCtxt<'tcx>,
218     pub ty_op: F,
219     pub lt_op: G,
220     pub ct_op: H,
221 }
222
223 impl<'tcx, F, G, H> TypeFolder<'tcx> for BottomUpFolder<'tcx, F, G, H>
224 where
225     F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
226     G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
227     H: FnMut(&'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx>,
228 {
229     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
230         self.tcx
231     }
232
233     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
234         let t = ty.super_fold_with(self);
235         (self.ty_op)(t)
236     }
237
238     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
239         let r = r.super_fold_with(self);
240         (self.lt_op)(r)
241     }
242
243     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
244         let ct = ct.super_fold_with(self);
245         (self.ct_op)(ct)
246     }
247 }
248
249 ///////////////////////////////////////////////////////////////////////////
250 // Region folder
251
252 impl<'tcx> TyCtxt<'tcx> {
253     /// Collects the free and escaping regions in `value` into `region_set`. Returns
254     /// whether any late-bound regions were skipped
255     pub fn collect_regions<T>(self, value: &T, region_set: &mut FxHashSet<ty::Region<'tcx>>) -> bool
256     where
257         T: TypeFoldable<'tcx>,
258     {
259         let mut have_bound_regions = false;
260         self.fold_regions(value, &mut have_bound_regions, |r, d| {
261             region_set.insert(self.mk_region(r.shifted_out_to_binder(d)));
262             r
263         });
264         have_bound_regions
265     }
266
267     /// Folds the escaping and free regions in `value` using `f`, and
268     /// sets `skipped_regions` to true if any late-bound region was found
269     /// and skipped.
270     pub fn fold_regions<T>(
271         self,
272         value: &T,
273         skipped_regions: &mut bool,
274         mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
275     ) -> T
276     where
277         T: TypeFoldable<'tcx>,
278     {
279         value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
280     }
281
282     /// Invoke `callback` on every region appearing free in `value`.
283     pub fn for_each_free_region(
284         self,
285         value: &impl TypeFoldable<'tcx>,
286         mut callback: impl FnMut(ty::Region<'tcx>),
287     ) {
288         self.any_free_region_meets(value, |r| {
289             callback(r);
290             false
291         });
292     }
293
294     /// Returns `true` if `callback` returns true for every region appearing free in `value`.
295     pub fn all_free_regions_meet(
296         self,
297         value: &impl TypeFoldable<'tcx>,
298         mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
299     ) -> bool {
300         !self.any_free_region_meets(value, |r| !callback(r))
301     }
302
303     /// Returns `true` if `callback` returns true for some region appearing free in `value`.
304     pub fn any_free_region_meets(
305         self,
306         value: &impl TypeFoldable<'tcx>,
307         callback: impl FnMut(ty::Region<'tcx>) -> bool,
308     ) -> bool {
309         return value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback });
310
311         struct RegionVisitor<F> {
312             /// The index of a binder *just outside* the things we have
313             /// traversed. If we encounter a bound region bound by this
314             /// binder or one outer to it, it appears free. Example:
315             ///
316             /// ```
317             ///    for<'a> fn(for<'b> fn(), T)
318             /// ^          ^          ^     ^
319             /// |          |          |     | here, would be shifted in 1
320             /// |          |          | here, would be shifted in 2
321             /// |          | here, would be `INNERMOST` shifted in by 1
322             /// | here, initially, binder would be `INNERMOST`
323             /// ```
324             ///
325             /// You see that, initially, *any* bound value is free,
326             /// because we've not traversed any binders. As we pass
327             /// through a binder, we shift the `outer_index` by 1 to
328             /// account for the new binder that encloses us.
329             outer_index: ty::DebruijnIndex,
330             callback: F,
331         }
332
333         impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
334         where
335             F: FnMut(ty::Region<'tcx>) -> bool,
336         {
337             fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
338                 self.outer_index.shift_in(1);
339                 let result = t.skip_binder().visit_with(self);
340                 self.outer_index.shift_out(1);
341                 result
342             }
343
344             fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
345                 match *r {
346                     ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
347                         false // ignore bound regions, keep visiting
348                     }
349                     _ => (self.callback)(r),
350                 }
351             }
352
353             fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
354                 // We're only interested in types involving regions
355                 if ty.flags.intersects(TypeFlags::HAS_FREE_REGIONS) {
356                     ty.super_visit_with(self)
357                 } else {
358                     false // keep visiting
359                 }
360             }
361         }
362     }
363 }
364
365 /// Folds over the substructure of a type, visiting its component
366 /// types and all regions that occur *free* within it.
367 ///
368 /// That is, `Ty` can contain function or method types that bind
369 /// regions at the call site (`ReLateBound`), and occurrences of
370 /// regions (aka "lifetimes") that are bound within a type are not
371 /// visited by this folder; only regions that occur free will be
372 /// visited by `fld_r`.
373
374 pub struct RegionFolder<'a, 'tcx> {
375     tcx: TyCtxt<'tcx>,
376     skipped_regions: &'a mut bool,
377
378     /// Stores the index of a binder *just outside* the stuff we have
379     /// visited.  So this begins as INNERMOST; when we pass through a
380     /// binder, it is incremented (via `shift_in`).
381     current_index: ty::DebruijnIndex,
382
383     /// Callback invokes for each free region. The `DebruijnIndex`
384     /// points to the binder *just outside* the ones we have passed
385     /// through.
386     fold_region_fn:
387         &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a),
388 }
389
390 impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
391     #[inline]
392     pub fn new(
393         tcx: TyCtxt<'tcx>,
394         skipped_regions: &'a mut bool,
395         fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
396     ) -> RegionFolder<'a, 'tcx> {
397         RegionFolder { tcx, skipped_regions, current_index: ty::INNERMOST, fold_region_fn }
398     }
399 }
400
401 impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
402     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
403         self.tcx
404     }
405
406     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
407         self.current_index.shift_in(1);
408         let t = t.super_fold_with(self);
409         self.current_index.shift_out(1);
410         t
411     }
412
413     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
414         match *r {
415             ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
416                 debug!(
417                     "RegionFolder.fold_region({:?}) skipped bound region (current index={:?})",
418                     r, self.current_index
419                 );
420                 *self.skipped_regions = true;
421                 r
422             }
423             _ => {
424                 debug!(
425                     "RegionFolder.fold_region({:?}) folding free region (current_index={:?})",
426                     r, self.current_index
427                 );
428                 (self.fold_region_fn)(r, self.current_index)
429             }
430         }
431     }
432 }
433
434 ///////////////////////////////////////////////////////////////////////////
435 // Bound vars replacer
436
437 /// Replaces the escaping bound vars (late bound regions or bound types) in a type.
438 struct BoundVarReplacer<'a, 'tcx> {
439     tcx: TyCtxt<'tcx>,
440
441     /// As with `RegionFolder`, represents the index of a binder *just outside*
442     /// the ones we have visited.
443     current_index: ty::DebruijnIndex,
444
445     fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
446     fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
447     fld_c: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx> + 'a),
448 }
449
450 impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> {
451     fn new<F, G, H>(tcx: TyCtxt<'tcx>, fld_r: &'a mut F, fld_t: &'a mut G, fld_c: &'a mut H) -> Self
452     where
453         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
454         G: FnMut(ty::BoundTy) -> Ty<'tcx>,
455         H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
456     {
457         BoundVarReplacer { tcx, current_index: ty::INNERMOST, fld_r, fld_t, fld_c }
458     }
459 }
460
461 impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
462     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
463         self.tcx
464     }
465
466     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
467         self.current_index.shift_in(1);
468         let t = t.super_fold_with(self);
469         self.current_index.shift_out(1);
470         t
471     }
472
473     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
474         match t.kind {
475             ty::Bound(debruijn, bound_ty) => {
476                 if debruijn == self.current_index {
477                     let fld_t = &mut self.fld_t;
478                     let ty = fld_t(bound_ty);
479                     ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32())
480                 } else {
481                     t
482                 }
483             }
484             _ => {
485                 if !t.has_vars_bound_at_or_above(self.current_index) {
486                     // Nothing more to substitute.
487                     t
488                 } else {
489                     t.super_fold_with(self)
490                 }
491             }
492         }
493     }
494
495     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
496         match *r {
497             ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
498                 let fld_r = &mut self.fld_r;
499                 let region = fld_r(br);
500                 if let ty::ReLateBound(debruijn1, br) = *region {
501                     // If the callback returns a late-bound region,
502                     // that region should always use the INNERMOST
503                     // debruijn index. Then we adjust it to the
504                     // correct depth.
505                     assert_eq!(debruijn1, ty::INNERMOST);
506                     self.tcx.mk_region(ty::ReLateBound(debruijn, br))
507                 } else {
508                     region
509                 }
510             }
511             _ => r,
512         }
513     }
514
515     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
516         if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } = *ct {
517             if debruijn == self.current_index {
518                 let fld_c = &mut self.fld_c;
519                 let ct = fld_c(bound_const, ty);
520                 ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32())
521             } else {
522                 ct
523             }
524         } else {
525             if !ct.has_vars_bound_at_or_above(self.current_index) {
526                 // Nothing more to substitute.
527                 ct
528             } else {
529                 ct.super_fold_with(self)
530             }
531         }
532     }
533 }
534
535 impl<'tcx> TyCtxt<'tcx> {
536     /// Replaces all regions bound by the given `Binder` with the
537     /// results returned by the closure; the closure is expected to
538     /// return a free region (relative to this binder), and hence the
539     /// binder is removed in the return type. The closure is invoked
540     /// once for each unique `BoundRegion`; multiple references to the
541     /// same `BoundRegion` will reuse the previous result. A map is
542     /// returned at the end with each bound region and the free region
543     /// that replaced it.
544     ///
545     /// This method only replaces late bound regions and the result may still
546     /// contain escaping bound types.
547     pub fn replace_late_bound_regions<T, F>(
548         self,
549         value: &Binder<T>,
550         fld_r: F,
551     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
552     where
553         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
554         T: TypeFoldable<'tcx>,
555     {
556         // identity for bound types and consts
557         let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty));
558         let fld_c = |bound_ct, ty| {
559             self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty })
560         };
561         self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c)
562     }
563
564     /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
565     /// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c`
566     /// closure replaces escaping bound consts.
567     pub fn replace_escaping_bound_vars<T, F, G, H>(
568         self,
569         value: &T,
570         mut fld_r: F,
571         mut fld_t: G,
572         mut fld_c: H,
573     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
574     where
575         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
576         G: FnMut(ty::BoundTy) -> Ty<'tcx>,
577         H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
578         T: TypeFoldable<'tcx>,
579     {
580         use rustc_data_structures::fx::FxHashMap;
581
582         let mut region_map = BTreeMap::new();
583         let mut type_map = FxHashMap::default();
584         let mut const_map = FxHashMap::default();
585
586         if !value.has_escaping_bound_vars() {
587             (value.clone(), region_map)
588         } else {
589             let mut real_fld_r = |br| *region_map.entry(br).or_insert_with(|| fld_r(br));
590
591             let mut real_fld_t =
592                 |bound_ty| *type_map.entry(bound_ty).or_insert_with(|| fld_t(bound_ty));
593
594             let mut real_fld_c =
595                 |bound_ct, ty| *const_map.entry(bound_ct).or_insert_with(|| fld_c(bound_ct, ty));
596
597             let mut replacer =
598                 BoundVarReplacer::new(self, &mut real_fld_r, &mut real_fld_t, &mut real_fld_c);
599             let result = value.fold_with(&mut replacer);
600             (result, region_map)
601         }
602     }
603
604     /// Replaces all types or regions bound by the given `Binder`. The `fld_r`
605     /// closure replaces bound regions while the `fld_t` closure replaces bound
606     /// types.
607     pub fn replace_bound_vars<T, F, G, H>(
608         self,
609         value: &Binder<T>,
610         fld_r: F,
611         fld_t: G,
612         fld_c: H,
613     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
614     where
615         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
616         G: FnMut(ty::BoundTy) -> Ty<'tcx>,
617         H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
618         T: TypeFoldable<'tcx>,
619     {
620         self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c)
621     }
622
623     /// Replaces any late-bound regions bound in `value` with
624     /// free variants attached to `all_outlive_scope`.
625     pub fn liberate_late_bound_regions<T>(
626         &self,
627         all_outlive_scope: DefId,
628         value: &ty::Binder<T>,
629     ) -> T
630     where
631         T: TypeFoldable<'tcx>,
632     {
633         self.replace_late_bound_regions(value, |br| {
634             self.mk_region(ty::ReFree(ty::FreeRegion {
635                 scope: all_outlive_scope,
636                 bound_region: br,
637             }))
638         })
639         .0
640     }
641
642     /// Returns a set of all late-bound regions that are constrained
643     /// by `value`, meaning that if we instantiate those LBR with
644     /// variables and equate `value` with something else, those
645     /// variables will also be equated.
646     pub fn collect_constrained_late_bound_regions<T>(
647         &self,
648         value: &Binder<T>,
649     ) -> FxHashSet<ty::BoundRegion>
650     where
651         T: TypeFoldable<'tcx>,
652     {
653         self.collect_late_bound_regions(value, true)
654     }
655
656     /// Returns a set of all late-bound regions that appear in `value` anywhere.
657     pub fn collect_referenced_late_bound_regions<T>(
658         &self,
659         value: &Binder<T>,
660     ) -> FxHashSet<ty::BoundRegion>
661     where
662         T: TypeFoldable<'tcx>,
663     {
664         self.collect_late_bound_regions(value, false)
665     }
666
667     fn collect_late_bound_regions<T>(
668         &self,
669         value: &Binder<T>,
670         just_constraint: bool,
671     ) -> FxHashSet<ty::BoundRegion>
672     where
673         T: TypeFoldable<'tcx>,
674     {
675         let mut collector = LateBoundRegionsCollector::new(just_constraint);
676         let result = value.skip_binder().visit_with(&mut collector);
677         assert!(!result); // should never have stopped early
678         collector.regions
679     }
680
681     /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
682     /// method lookup and a few other places where precise region relationships are not required.
683     pub fn erase_late_bound_regions<T>(self, value: &Binder<T>) -> T
684     where
685         T: TypeFoldable<'tcx>,
686     {
687         self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
688     }
689
690     /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
691     /// assigned starting at 1 and increasing monotonically in the order traversed
692     /// by the fold operation.
693     ///
694     /// The chief purpose of this function is to canonicalize regions so that two
695     /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
696     /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
697     /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
698     pub fn anonymize_late_bound_regions<T>(self, sig: &Binder<T>) -> Binder<T>
699     where
700         T: TypeFoldable<'tcx>,
701     {
702         let mut counter = 0;
703         Binder::bind(
704             self.replace_late_bound_regions(sig, |_| {
705                 counter += 1;
706                 self.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(counter)))
707             })
708             .0,
709         )
710     }
711 }
712
713 ///////////////////////////////////////////////////////////////////////////
714 // Shifter
715 //
716 // Shifts the De Bruijn indices on all escaping bound vars by a
717 // fixed amount. Useful in substitution or when otherwise introducing
718 // a binding level that is not intended to capture the existing bound
719 // vars. See comment on `shift_vars_through_binders` method in
720 // `subst.rs` for more details.
721
722 enum Direction {
723     In,
724     Out,
725 }
726
727 struct Shifter<'tcx> {
728     tcx: TyCtxt<'tcx>,
729     current_index: ty::DebruijnIndex,
730     amount: u32,
731     direction: Direction,
732 }
733
734 impl Shifter<'tcx> {
735     pub fn new(tcx: TyCtxt<'tcx>, amount: u32, direction: Direction) -> Self {
736         Shifter { tcx, current_index: ty::INNERMOST, amount, direction }
737     }
738 }
739
740 impl TypeFolder<'tcx> for Shifter<'tcx> {
741     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
742         self.tcx
743     }
744
745     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
746         self.current_index.shift_in(1);
747         let t = t.super_fold_with(self);
748         self.current_index.shift_out(1);
749         t
750     }
751
752     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
753         match *r {
754             ty::ReLateBound(debruijn, br) => {
755                 if self.amount == 0 || debruijn < self.current_index {
756                     r
757                 } else {
758                     let debruijn = match self.direction {
759                         Direction::In => debruijn.shifted_in(self.amount),
760                         Direction::Out => {
761                             assert!(debruijn.as_u32() >= self.amount);
762                             debruijn.shifted_out(self.amount)
763                         }
764                     };
765                     let shifted = ty::ReLateBound(debruijn, br);
766                     self.tcx.mk_region(shifted)
767                 }
768             }
769             _ => r,
770         }
771     }
772
773     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
774         match ty.kind {
775             ty::Bound(debruijn, bound_ty) => {
776                 if self.amount == 0 || debruijn < self.current_index {
777                     ty
778                 } else {
779                     let debruijn = match self.direction {
780                         Direction::In => debruijn.shifted_in(self.amount),
781                         Direction::Out => {
782                             assert!(debruijn.as_u32() >= self.amount);
783                             debruijn.shifted_out(self.amount)
784                         }
785                     };
786                     self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
787                 }
788             }
789
790             _ => ty.super_fold_with(self),
791         }
792     }
793
794     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
795         if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct {
796             if self.amount == 0 || debruijn < self.current_index {
797                 ct
798             } else {
799                 let debruijn = match self.direction {
800                     Direction::In => debruijn.shifted_in(self.amount),
801                     Direction::Out => {
802                         assert!(debruijn.as_u32() >= self.amount);
803                         debruijn.shifted_out(self.amount)
804                     }
805                 };
806                 self.tcx.mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty })
807             }
808         } else {
809             ct.super_fold_with(self)
810         }
811     }
812 }
813
814 pub fn shift_region<'tcx>(
815     tcx: TyCtxt<'tcx>,
816     region: ty::Region<'tcx>,
817     amount: u32,
818 ) -> ty::Region<'tcx> {
819     match region {
820         ty::ReLateBound(debruijn, br) if amount > 0 => {
821             tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br))
822         }
823         _ => region,
824     }
825 }
826
827 pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: &T, amount: u32) -> T
828 where
829     T: TypeFoldable<'tcx>,
830 {
831     debug!("shift_vars(value={:?}, amount={})", value, amount);
832
833     value.fold_with(&mut Shifter::new(tcx, amount, Direction::In))
834 }
835
836 pub fn shift_out_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: &T, amount: u32) -> T
837 where
838     T: TypeFoldable<'tcx>,
839 {
840     debug!("shift_out_vars(value={:?}, amount={})", value, amount);
841
842     value.fold_with(&mut Shifter::new(tcx, amount, Direction::Out))
843 }
844
845 /// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
846 /// bound region or a bound type.
847 ///
848 /// So, for example, consider a type like the following, which has two binders:
849 ///
850 ///    for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
851 ///    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
852 ///                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~  inner scope
853 ///
854 /// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
855 /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
856 /// fn type*, that type has an escaping region: `'a`.
857 ///
858 /// Note that what I'm calling an "escaping var" is often just called a "free var". However,
859 /// we already use the term "free var". It refers to the regions or types that we use to represent
860 /// bound regions or type params on a fn definition while we are type checking its body.
861 ///
862 /// To clarify, conceptually there is no particular difference between
863 /// an "escaping" var and a "free" var. However, there is a big
864 /// difference in practice. Basically, when "entering" a binding
865 /// level, one is generally required to do some sort of processing to
866 /// a bound var, such as replacing it with a fresh/placeholder
867 /// var, or making an entry in the environment to represent the
868 /// scope to which it is attached, etc. An escaping var represents
869 /// a bound var for which this processing has not yet been done.
870 struct HasEscapingVarsVisitor {
871     /// Anything bound by `outer_index` or "above" is escaping.
872     outer_index: ty::DebruijnIndex,
873 }
874
875 impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
876     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
877         self.outer_index.shift_in(1);
878         let result = t.super_visit_with(self);
879         self.outer_index.shift_out(1);
880         result
881     }
882
883     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
884         // If the outer-exclusive-binder is *strictly greater* than
885         // `outer_index`, that means that `t` contains some content
886         // bound at `outer_index` or above (because
887         // `outer_exclusive_binder` is always 1 higher than the
888         // content in `t`). Therefore, `t` has some escaping vars.
889         t.outer_exclusive_binder > self.outer_index
890     }
891
892     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
893         // If the region is bound by `outer_index` or anything outside
894         // of outer index, then it escapes the binders we have
895         // visited.
896         r.bound_at_or_above_binder(self.outer_index)
897     }
898
899     fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
900         // we don't have a `visit_infer_const` callback, so we have to
901         // hook in here to catch this case (annoying...), but
902         // otherwise we do want to remember to visit the rest of the
903         // const, as it has types/regions embedded in a lot of other
904         // places.
905         match ct.val {
906             ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => true,
907             _ => ct.super_visit_with(self),
908         }
909     }
910 }
911
912 // FIXME: Optimize for checking for infer flags
913 struct HasTypeFlagsVisitor {
914     flags: ty::TypeFlags,
915 }
916
917 impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
918     fn visit_ty(&mut self, t: Ty<'_>) -> bool {
919         debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, t.flags, self.flags);
920         t.flags.intersects(self.flags)
921     }
922
923     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
924         let flags = r.type_flags();
925         debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags);
926         flags.intersects(self.flags)
927     }
928
929     fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
930         let flags = FlagComputation::for_const(c);
931         debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
932         flags.intersects(self.flags)
933     }
934 }
935
936 /// Collects all the late-bound regions at the innermost binding level
937 /// into a hash set.
938 struct LateBoundRegionsCollector {
939     current_index: ty::DebruijnIndex,
940     regions: FxHashSet<ty::BoundRegion>,
941
942     /// `true` if we only want regions that are known to be
943     /// "constrained" when you equate this type with another type. In
944     /// particular, if you have e.g., `&'a u32` and `&'b u32`, equating
945     /// them constraints `'a == 'b`. But if you have `<&'a u32 as
946     /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those
947     /// types may mean that `'a` and `'b` don't appear in the results,
948     /// so they are not considered *constrained*.
949     just_constrained: bool,
950 }
951
952 impl LateBoundRegionsCollector {
953     fn new(just_constrained: bool) -> Self {
954         LateBoundRegionsCollector {
955             current_index: ty::INNERMOST,
956             regions: Default::default(),
957             just_constrained,
958         }
959     }
960 }
961
962 impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
963     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
964         self.current_index.shift_in(1);
965         let result = t.super_visit_with(self);
966         self.current_index.shift_out(1);
967         result
968     }
969
970     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
971         // if we are only looking for "constrained" region, we have to
972         // ignore the inputs to a projection, as they may not appear
973         // in the normalized form
974         if self.just_constrained {
975             match t.kind {
976                 ty::Projection(..) | ty::Opaque(..) => {
977                     return false;
978                 }
979                 _ => {}
980             }
981         }
982
983         t.super_visit_with(self)
984     }
985
986     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
987         if let ty::ReLateBound(debruijn, br) = *r {
988             if debruijn == self.current_index {
989                 self.regions.insert(br);
990             }
991         }
992         false
993     }
994 }