]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/fold.rs
fix most compiler/ doctests
[rust.git] / compiler / rustc_middle / src / ty / fold.rs
1 //! A generalized traversal mechanism for complex data structures that contain
2 //! type information.
3 //!
4 //! There are two types of traversal.
5 //! - Folding. This is a modifying traversal. It consumes the data structure,
6 //!   producing a (possibly) modified version of it. Both fallible and
7 //!   infallible versions are available. The name is potentially
8 //!   confusing, because this traversal is more like `Iterator::map` than
9 //!   `Iterator::fold`.
10 //! - Visiting. This is a read-only traversal of the data structure.
11 //!
12 //! These traversals have limited flexibility. Only a small number of "types of
13 //! interest" within the complex data structures can receive custom
14 //! modification (when folding) or custom visitation (when visiting). These are
15 //! the ones containing the most important type-related information, such as
16 //! `Ty`, `Predicate`, `Region`, and `Const`.
17 //!
18 //! There are two traits involved in each traversal type.
19 //! - The first trait is `TypeFoldable`, which is implemented once for many
20 //!   types. This includes both (a) types of interest, and (b) all other
21 //!   relevant types, including generic containers like `Vec` and `Option`. It
22 //!   defines a "skeleton" of how they should be traversed, for both folding
23 //!   and visiting.
24 //! - The second trait is `TypeFolder`/`FallibleTypeFolder` (for
25 //!   infallible/fallible folding traversals) or `TypeVisitor` (for visiting
26 //!   traversals). One of these is implemented for each folder/visitor. This
27 //!   defines how types of interest are handled.
28 //!
29 //! This means each traversal is a mixture of (a) generic traversal operations,
30 //! and (b) custom fold/visit operations that are specific to the
31 //! folder/visitor.
32 //! - The `TypeFoldable` impls handle most of the traversal, and call into
33 //!   `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a
34 //!   type of interest.
35 //! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call back into
36 //!   a `TypeFoldable` impl, because (a) the types of interest are recursive
37 //!   and can contain other types of interest, and (b) each folder/visitor
38 //!   might provide custom handling only for some types of interest, or only
39 //!   for some variants of each type of interest, and then use default
40 //!   traversal for the remaining cases.
41 //!
42 //! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
43 //! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so:
44 //! ```text
45 //! s.visit_with(visitor) calls
46 //! - s.super_visit_with(visitor) calls
47 //!   - ty.visit_with(visitor) calls
48 //!     - visitor.visit_ty(ty) may call
49 //!       - ty.super_visit_with(visitor)
50 //!   - u.visit_with(visitor)
51 //! ```
52 use crate::mir;
53 use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
54 use rustc_errors::ErrorGuaranteed;
55 use rustc_hir::def_id::DefId;
56
57 use rustc_data_structures::fx::FxHashSet;
58 use rustc_data_structures::sso::SsoHashSet;
59 use std::collections::BTreeMap;
60 use std::fmt;
61 use std::ops::ControlFlow;
62
63 /// This trait is implemented for every type that can be folded/visited,
64 /// providing the skeleton of the traversal.
65 ///
66 /// To implement this conveniently, use the derive macro located in
67 /// `rustc_macros`.
68 pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
69     /// The main entry point for folding. To fold a value `t` with a folder `f`
70     /// call: `t.try_fold_with(f)`.
71     ///
72     /// For types of interest (such as `Ty`), this default is overridden with a
73     /// method that calls a folder method specifically for that type (such as
74     /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
75     /// to `TypeFolder`.
76     ///
77     /// For other types, this default is used.
78     fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
79         self.try_super_fold_with(folder)
80     }
81
82     /// A convenient alternative to `try_fold_with` for use with infallible
83     /// folders. Do not override this method, to ensure coherence with
84     /// `try_fold_with`.
85     fn fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
86         self.try_fold_with(folder).into_ok()
87     }
88
89     /// Traverses the type in question, typically by calling `try_fold_with` on
90     /// each field/element. This is true even for types of interest such as
91     /// `Ty`. This should only be called within `TypeFolder` methods, when
92     /// non-custom traversals are desired for types of interest.
93     fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
94         self,
95         folder: &mut F,
96     ) -> Result<Self, F::Error>;
97
98     /// A convenient alternative to `try_super_fold_with` for use with
99     /// infallible folders. Do not override this method, to ensure coherence
100     /// with `try_super_fold_with`.
101     fn super_fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
102         self.try_super_fold_with(folder).into_ok()
103     }
104
105     /// The entry point for visiting. To visit a value `t` with a visitor `v`
106     /// call: `t.visit_with(v)`.
107     ///
108     /// For types of interest (such as `Ty`), this default is overridden with a
109     /// method that calls a visitor method specifically for that type (such as
110     /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
111     /// `TypeVisitor`.
112     ///
113     /// For other types, this default is used.
114     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
115         self.super_visit_with(visitor)
116     }
117
118     /// Traverses the type in question, typically by calling `visit_with` on
119     /// each field/element. This is true even for types of interest such as
120     /// `Ty`. This should only be called within `TypeVisitor` methods, when
121     /// non-custom traversals are desired for types of interest.
122     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
123
124     /// Returns `true` if `self` has any late-bound regions that are either
125     /// bound by `binder` or bound by some binder outside of `binder`.
126     /// If `binder` is `ty::INNERMOST`, this indicates whether
127     /// there are any late-bound regions that appear free.
128     fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
129         self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break()
130     }
131
132     /// Returns `true` if this `self` has any regions that escape `binder` (and
133     /// hence are not bound by it).
134     fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
135         self.has_vars_bound_at_or_above(binder.shifted_in(1))
136     }
137
138     fn has_escaping_bound_vars(&self) -> bool {
139         self.has_vars_bound_at_or_above(ty::INNERMOST)
140     }
141
142     #[instrument(level = "trace")]
143     fn has_type_flags(&self, flags: TypeFlags) -> bool {
144         self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
145     }
146     fn has_projections(&self) -> bool {
147         self.has_type_flags(TypeFlags::HAS_PROJECTION)
148     }
149     fn has_opaque_types(&self) -> bool {
150         self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
151     }
152     fn references_error(&self) -> bool {
153         self.has_type_flags(TypeFlags::HAS_ERROR)
154     }
155     fn error_reported(&self) -> Option<ErrorGuaranteed> {
156         if self.references_error() {
157             Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
158         } else {
159             None
160         }
161     }
162     fn has_param_types_or_consts(&self) -> bool {
163         self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
164     }
165     fn has_infer_regions(&self) -> bool {
166         self.has_type_flags(TypeFlags::HAS_RE_INFER)
167     }
168     fn has_infer_types(&self) -> bool {
169         self.has_type_flags(TypeFlags::HAS_TY_INFER)
170     }
171     fn has_infer_types_or_consts(&self) -> bool {
172         self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
173     }
174     fn needs_infer(&self) -> bool {
175         self.has_type_flags(TypeFlags::NEEDS_INFER)
176     }
177     fn has_placeholders(&self) -> bool {
178         self.has_type_flags(
179             TypeFlags::HAS_RE_PLACEHOLDER
180                 | TypeFlags::HAS_TY_PLACEHOLDER
181                 | TypeFlags::HAS_CT_PLACEHOLDER,
182         )
183     }
184     fn needs_subst(&self) -> bool {
185         self.has_type_flags(TypeFlags::NEEDS_SUBST)
186     }
187     /// "Free" regions in this context means that it has any region
188     /// that is not (a) erased or (b) late-bound.
189     fn has_free_regions(&self) -> bool {
190         self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
191     }
192
193     fn has_erased_regions(&self) -> bool {
194         self.has_type_flags(TypeFlags::HAS_RE_ERASED)
195     }
196
197     /// True if there are any un-erased free regions.
198     fn has_erasable_regions(&self) -> bool {
199         self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
200     }
201
202     /// Indicates whether this value references only 'global'
203     /// generic parameters that are the same regardless of what fn we are
204     /// in. This is used for caching.
205     fn is_global(&self) -> bool {
206         !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
207     }
208
209     /// True if there are any late-bound regions
210     fn has_late_bound_regions(&self) -> bool {
211         self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
212     }
213
214     /// Indicates whether this value still has parameters/placeholders/inference variables
215     /// which could be replaced later, in a way that would change the results of `impl`
216     /// specialization.
217     fn still_further_specializable(&self) -> bool {
218         self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
219     }
220 }
221
222 /// This trait is implemented for every folding traversal. There is a fold
223 /// method defined for every type of interest. Each such method has a default
224 /// that does an "identity" fold.
225 ///
226 /// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`]
227 /// associated type is something other than the default `!`) then
228 /// [`FallibleTypeFolder`] should be implemented manually. Otherwise,
229 /// a blanket implementation of [`FallibleTypeFolder`] will defer to
230 /// the infallible methods of this trait to ensure that the two APIs
231 /// are coherent.
232 pub trait TypeFolder<'tcx>: Sized {
233     type Error = !;
234
235     fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
236
237     fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
238     where
239         T: TypeFoldable<'tcx>,
240         Self: TypeFolder<'tcx, Error = !>,
241     {
242         t.super_fold_with(self)
243     }
244
245     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx>
246     where
247         Self: TypeFolder<'tcx, Error = !>,
248     {
249         t.super_fold_with(self)
250     }
251
252     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx>
253     where
254         Self: TypeFolder<'tcx, Error = !>,
255     {
256         r.super_fold_with(self)
257     }
258
259     fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx>
260     where
261         Self: TypeFolder<'tcx, Error = !>,
262     {
263         c.super_fold_with(self)
264     }
265
266     fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx>
267     where
268         Self: TypeFolder<'tcx, Error = !>,
269     {
270         p.super_fold_with(self)
271     }
272
273     fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx>
274     where
275         Self: TypeFolder<'tcx, Error = !>,
276     {
277         bug!("most type folders should not be folding MIR datastructures: {:?}", c)
278     }
279 }
280
281 /// This trait is implemented for every folding traversal. There is a fold
282 /// method defined for every type of interest. Each such method has a default
283 /// that does an "identity" fold.
284 ///
285 /// A blanket implementation of this trait (that defers to the relevant
286 /// method of [`TypeFolder`]) is provided for all infallible folders in
287 /// order to ensure the two APIs are coherent.
288 pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> {
289     fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
290     where
291         T: TypeFoldable<'tcx>,
292     {
293         t.try_super_fold_with(self)
294     }
295
296     fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
297         t.try_super_fold_with(self)
298     }
299
300     fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
301         r.try_super_fold_with(self)
302     }
303
304     fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
305         c.try_super_fold_with(self)
306     }
307
308     fn try_fold_predicate(
309         &mut self,
310         p: ty::Predicate<'tcx>,
311     ) -> Result<ty::Predicate<'tcx>, Self::Error> {
312         p.try_super_fold_with(self)
313     }
314
315     fn try_fold_mir_const(
316         &mut self,
317         c: mir::ConstantKind<'tcx>,
318     ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
319         bug!("most type folders should not be folding MIR datastructures: {:?}", c)
320     }
321 }
322
323 // This blanket implementation of the fallible trait for infallible folders
324 // delegates to infallible methods to ensure coherence.
325 impl<'tcx, F> FallibleTypeFolder<'tcx> for F
326 where
327     F: TypeFolder<'tcx, Error = !>,
328 {
329     fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
330     where
331         T: TypeFoldable<'tcx>,
332     {
333         Ok(self.fold_binder(t))
334     }
335
336     fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
337         Ok(self.fold_ty(t))
338     }
339
340     fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
341         Ok(self.fold_region(r))
342     }
343
344     fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
345         Ok(self.fold_const(c))
346     }
347
348     fn try_fold_predicate(
349         &mut self,
350         p: ty::Predicate<'tcx>,
351     ) -> Result<ty::Predicate<'tcx>, Self::Error> {
352         Ok(self.fold_predicate(p))
353     }
354
355     fn try_fold_mir_const(
356         &mut self,
357         c: mir::ConstantKind<'tcx>,
358     ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
359         Ok(self.fold_mir_const(c))
360     }
361 }
362
363 /// This trait is implemented for every visiting traversal. There is a visit
364 /// method defined for every type of interest. Each such method has a default
365 /// that recurses into the type's fields in a non-custom fashion.
366 pub trait TypeVisitor<'tcx>: Sized {
367     type BreakTy = !;
368
369     fn visit_binder<T: TypeFoldable<'tcx>>(
370         &mut self,
371         t: &Binder<'tcx, T>,
372     ) -> ControlFlow<Self::BreakTy> {
373         t.super_visit_with(self)
374     }
375
376     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
377         t.super_visit_with(self)
378     }
379
380     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
381         r.super_visit_with(self)
382     }
383
384     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
385         c.super_visit_with(self)
386     }
387
388     fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
389         uv.super_visit_with(self)
390     }
391
392     fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
393         p.super_visit_with(self)
394     }
395 }
396
397 ///////////////////////////////////////////////////////////////////////////
398 // Some sample folders
399
400 pub struct BottomUpFolder<'tcx, F, G, H>
401 where
402     F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
403     G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
404     H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
405 {
406     pub tcx: TyCtxt<'tcx>,
407     pub ty_op: F,
408     pub lt_op: G,
409     pub ct_op: H,
410 }
411
412 impl<'tcx, F, G, H> TypeFolder<'tcx> for BottomUpFolder<'tcx, F, G, H>
413 where
414     F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
415     G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
416     H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
417 {
418     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
419         self.tcx
420     }
421
422     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
423         let t = ty.super_fold_with(self);
424         (self.ty_op)(t)
425     }
426
427     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
428         let r = r.super_fold_with(self);
429         (self.lt_op)(r)
430     }
431
432     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
433         let ct = ct.super_fold_with(self);
434         (self.ct_op)(ct)
435     }
436 }
437
438 ///////////////////////////////////////////////////////////////////////////
439 // Region folder
440
441 impl<'tcx> TyCtxt<'tcx> {
442     /// Folds the escaping and free regions in `value` using `f`, and
443     /// sets `skipped_regions` to true if any late-bound region was found
444     /// and skipped.
445     pub fn fold_regions<T>(
446         self,
447         value: T,
448         skipped_regions: &mut bool,
449         mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
450     ) -> T
451     where
452         T: TypeFoldable<'tcx>,
453     {
454         value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
455     }
456
457     /// Invoke `callback` on every region appearing free in `value`.
458     pub fn for_each_free_region(
459         self,
460         value: &impl TypeFoldable<'tcx>,
461         mut callback: impl FnMut(ty::Region<'tcx>),
462     ) {
463         self.any_free_region_meets(value, |r| {
464             callback(r);
465             false
466         });
467     }
468
469     /// Returns `true` if `callback` returns true for every region appearing free in `value`.
470     pub fn all_free_regions_meet(
471         self,
472         value: &impl TypeFoldable<'tcx>,
473         mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
474     ) -> bool {
475         !self.any_free_region_meets(value, |r| !callback(r))
476     }
477
478     /// Returns `true` if `callback` returns true for some region appearing free in `value`.
479     pub fn any_free_region_meets(
480         self,
481         value: &impl TypeFoldable<'tcx>,
482         callback: impl FnMut(ty::Region<'tcx>) -> bool,
483     ) -> bool {
484         struct RegionVisitor<F> {
485             /// The index of a binder *just outside* the things we have
486             /// traversed. If we encounter a bound region bound by this
487             /// binder or one outer to it, it appears free. Example:
488             ///
489             /// ```ignore (illustrative)
490             ///       for<'a> fn(for<'b> fn(), T)
491             /// // ^          ^          ^     ^
492             /// // |          |          |     | here, would be shifted in 1
493             /// // |          |          | here, would be shifted in 2
494             /// // |          | here, would be `INNERMOST` shifted in by 1
495             /// // | here, initially, binder would be `INNERMOST`
496             /// ```
497             ///
498             /// You see that, initially, *any* bound value is free,
499             /// because we've not traversed any binders. As we pass
500             /// through a binder, we shift the `outer_index` by 1 to
501             /// account for the new binder that encloses us.
502             outer_index: ty::DebruijnIndex,
503             callback: F,
504         }
505
506         impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
507         where
508             F: FnMut(ty::Region<'tcx>) -> bool,
509         {
510             type BreakTy = ();
511
512             fn visit_binder<T: TypeFoldable<'tcx>>(
513                 &mut self,
514                 t: &Binder<'tcx, T>,
515             ) -> ControlFlow<Self::BreakTy> {
516                 self.outer_index.shift_in(1);
517                 let result = t.as_ref().skip_binder().visit_with(self);
518                 self.outer_index.shift_out(1);
519                 result
520             }
521
522             fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
523                 match *r {
524                     ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
525                         ControlFlow::CONTINUE
526                     }
527                     _ => {
528                         if (self.callback)(r) {
529                             ControlFlow::BREAK
530                         } else {
531                             ControlFlow::CONTINUE
532                         }
533                     }
534                 }
535             }
536
537             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
538                 // We're only interested in types involving regions
539                 if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
540                     ty.super_visit_with(self)
541                 } else {
542                     ControlFlow::CONTINUE
543                 }
544             }
545         }
546
547         value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break()
548     }
549 }
550
551 /// Folds over the substructure of a type, visiting its component
552 /// types and all regions that occur *free* within it.
553 ///
554 /// That is, `Ty` can contain function or method types that bind
555 /// regions at the call site (`ReLateBound`), and occurrences of
556 /// regions (aka "lifetimes") that are bound within a type are not
557 /// visited by this folder; only regions that occur free will be
558 /// visited by `fld_r`.
559
560 pub struct RegionFolder<'a, 'tcx> {
561     tcx: TyCtxt<'tcx>,
562     skipped_regions: &'a mut bool,
563
564     /// Stores the index of a binder *just outside* the stuff we have
565     /// visited.  So this begins as INNERMOST; when we pass through a
566     /// binder, it is incremented (via `shift_in`).
567     current_index: ty::DebruijnIndex,
568
569     /// Callback invokes for each free region. The `DebruijnIndex`
570     /// points to the binder *just outside* the ones we have passed
571     /// through.
572     fold_region_fn:
573         &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a),
574 }
575
576 impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
577     #[inline]
578     pub fn new(
579         tcx: TyCtxt<'tcx>,
580         skipped_regions: &'a mut bool,
581         fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
582     ) -> RegionFolder<'a, 'tcx> {
583         RegionFolder { tcx, skipped_regions, current_index: ty::INNERMOST, fold_region_fn }
584     }
585 }
586
587 impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
588     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
589         self.tcx
590     }
591
592     fn fold_binder<T: TypeFoldable<'tcx>>(
593         &mut self,
594         t: ty::Binder<'tcx, T>,
595     ) -> ty::Binder<'tcx, T> {
596         self.current_index.shift_in(1);
597         let t = t.super_fold_with(self);
598         self.current_index.shift_out(1);
599         t
600     }
601
602     #[instrument(skip(self), level = "debug")]
603     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
604         match *r {
605             ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
606                 debug!(?self.current_index, "skipped bound region");
607                 *self.skipped_regions = true;
608                 r
609             }
610             _ => {
611                 debug!(?self.current_index, "folding free region");
612                 (self.fold_region_fn)(r, self.current_index)
613             }
614         }
615     }
616 }
617
618 ///////////////////////////////////////////////////////////////////////////
619 // Bound vars replacer
620
621 /// Replaces the escaping bound vars (late bound regions or bound types) in a type.
622 struct BoundVarReplacer<'a, 'tcx> {
623     tcx: TyCtxt<'tcx>,
624
625     /// As with `RegionFolder`, represents the index of a binder *just outside*
626     /// the ones we have visited.
627     current_index: ty::DebruijnIndex,
628
629     fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>,
630     fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>,
631     fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a)>,
632 }
633
634 impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> {
635     fn new(
636         tcx: TyCtxt<'tcx>,
637         fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>,
638         fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>,
639         fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a)>,
640     ) -> Self {
641         BoundVarReplacer { tcx, current_index: ty::INNERMOST, fld_r, fld_t, fld_c }
642     }
643 }
644
645 impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
646     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
647         self.tcx
648     }
649
650     fn fold_binder<T: TypeFoldable<'tcx>>(
651         &mut self,
652         t: ty::Binder<'tcx, T>,
653     ) -> ty::Binder<'tcx, T> {
654         self.current_index.shift_in(1);
655         let t = t.super_fold_with(self);
656         self.current_index.shift_out(1);
657         t
658     }
659
660     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
661         match *t.kind() {
662             ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
663                 if let Some(fld_t) = self.fld_t.as_mut() {
664                     let ty = fld_t(bound_ty);
665                     return ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32());
666                 }
667             }
668             _ if t.has_vars_bound_at_or_above(self.current_index) => {
669                 return t.super_fold_with(self);
670             }
671             _ => {}
672         }
673         t
674     }
675
676     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
677         match *r {
678             ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
679                 if let Some(fld_r) = self.fld_r.as_mut() {
680                     let region = fld_r(br);
681                     return if let ty::ReLateBound(debruijn1, br) = *region {
682                         // If the callback returns a late-bound region,
683                         // that region should always use the INNERMOST
684                         // debruijn index. Then we adjust it to the
685                         // correct depth.
686                         assert_eq!(debruijn1, ty::INNERMOST);
687                         self.tcx.mk_region(ty::ReLateBound(debruijn, br))
688                     } else {
689                         region
690                     };
691                 }
692             }
693             _ => {}
694         }
695         r
696     }
697
698     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
699         match ct.val() {
700             ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
701                 if let Some(fld_c) = self.fld_c.as_mut() {
702                     let ct = fld_c(bound_const, ct.ty());
703                     return ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32());
704                 }
705             }
706             _ if ct.has_vars_bound_at_or_above(self.current_index) => {
707                 return ct.super_fold_with(self);
708             }
709             _ => {}
710         }
711         ct
712     }
713 }
714
715 impl<'tcx> TyCtxt<'tcx> {
716     /// Replaces all regions bound by the given `Binder` with the
717     /// results returned by the closure; the closure is expected to
718     /// return a free region (relative to this binder), and hence the
719     /// binder is removed in the return type. The closure is invoked
720     /// once for each unique `BoundRegionKind`; multiple references to the
721     /// same `BoundRegionKind` will reuse the previous result. A map is
722     /// returned at the end with each bound region and the free region
723     /// that replaced it.
724     ///
725     /// This method only replaces late bound regions and the result may still
726     /// contain escaping bound types.
727     pub fn replace_late_bound_regions<T, F>(
728         self,
729         value: Binder<'tcx, T>,
730         mut fld_r: F,
731     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
732     where
733         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
734         T: TypeFoldable<'tcx>,
735     {
736         let mut region_map = BTreeMap::new();
737         let mut real_fld_r =
738             |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
739         let value = value.skip_binder();
740         let value = if !value.has_escaping_bound_vars() {
741             value
742         } else {
743             let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None);
744             value.fold_with(&mut replacer)
745         };
746         (value, region_map)
747     }
748
749     /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
750     /// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c`
751     /// closure replaces escaping bound consts.
752     pub fn replace_escaping_bound_vars<T, F, G, H>(
753         self,
754         value: T,
755         mut fld_r: F,
756         mut fld_t: G,
757         mut fld_c: H,
758     ) -> T
759     where
760         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
761         G: FnMut(ty::BoundTy) -> Ty<'tcx>,
762         H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>,
763         T: TypeFoldable<'tcx>,
764     {
765         if !value.has_escaping_bound_vars() {
766             value
767         } else {
768             let mut replacer =
769                 BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c));
770             value.fold_with(&mut replacer)
771         }
772     }
773
774     /// Replaces all types or regions bound by the given `Binder`. The `fld_r`
775     /// closure replaces bound regions while the `fld_t` closure replaces bound
776     /// types.
777     pub fn replace_bound_vars<T, F, G, H>(
778         self,
779         value: Binder<'tcx, T>,
780         mut fld_r: F,
781         fld_t: G,
782         fld_c: H,
783     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
784     where
785         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
786         G: FnMut(ty::BoundTy) -> Ty<'tcx>,
787         H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>,
788         T: TypeFoldable<'tcx>,
789     {
790         let mut region_map = BTreeMap::new();
791         let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
792         let value = self.replace_escaping_bound_vars(value.skip_binder(), real_fld_r, fld_t, fld_c);
793         (value, region_map)
794     }
795
796     /// Replaces any late-bound regions bound in `value` with
797     /// free variants attached to `all_outlive_scope`.
798     pub fn liberate_late_bound_regions<T>(
799         self,
800         all_outlive_scope: DefId,
801         value: ty::Binder<'tcx, T>,
802     ) -> T
803     where
804         T: TypeFoldable<'tcx>,
805     {
806         self.replace_late_bound_regions(value, |br| {
807             self.mk_region(ty::ReFree(ty::FreeRegion {
808                 scope: all_outlive_scope,
809                 bound_region: br.kind,
810             }))
811         })
812         .0
813     }
814
815     pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
816     where
817         T: TypeFoldable<'tcx>,
818     {
819         self.replace_escaping_bound_vars(
820             value,
821             |r| {
822                 self.mk_region(ty::ReLateBound(
823                     ty::INNERMOST,
824                     ty::BoundRegion {
825                         var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars),
826                         kind: r.kind,
827                     },
828                 ))
829             },
830             |t| {
831                 self.mk_ty(ty::Bound(
832                     ty::INNERMOST,
833                     ty::BoundTy {
834                         var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars),
835                         kind: t.kind,
836                     },
837                 ))
838             },
839             |c, ty| {
840                 self.mk_const(ty::ConstS {
841                     val: ty::ConstKind::Bound(
842                         ty::INNERMOST,
843                         ty::BoundVar::from_usize(c.as_usize() + bound_vars),
844                     ),
845                     ty,
846                 })
847             },
848         )
849     }
850
851     /// Returns a set of all late-bound regions that are constrained
852     /// by `value`, meaning that if we instantiate those LBR with
853     /// variables and equate `value` with something else, those
854     /// variables will also be equated.
855     pub fn collect_constrained_late_bound_regions<T>(
856         self,
857         value: &Binder<'tcx, T>,
858     ) -> FxHashSet<ty::BoundRegionKind>
859     where
860         T: TypeFoldable<'tcx>,
861     {
862         self.collect_late_bound_regions(value, true)
863     }
864
865     /// Returns a set of all late-bound regions that appear in `value` anywhere.
866     pub fn collect_referenced_late_bound_regions<T>(
867         self,
868         value: &Binder<'tcx, T>,
869     ) -> FxHashSet<ty::BoundRegionKind>
870     where
871         T: TypeFoldable<'tcx>,
872     {
873         self.collect_late_bound_regions(value, false)
874     }
875
876     fn collect_late_bound_regions<T>(
877         self,
878         value: &Binder<'tcx, T>,
879         just_constraint: bool,
880     ) -> FxHashSet<ty::BoundRegionKind>
881     where
882         T: TypeFoldable<'tcx>,
883     {
884         let mut collector = LateBoundRegionsCollector::new(just_constraint);
885         let result = value.as_ref().skip_binder().visit_with(&mut collector);
886         assert!(result.is_continue()); // should never have stopped early
887         collector.regions
888     }
889
890     /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
891     /// method lookup and a few other places where precise region relationships are not required.
892     pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
893     where
894         T: TypeFoldable<'tcx>,
895     {
896         self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
897     }
898
899     /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
900     /// assigned starting at 0 and increasing monotonically in the order traversed
901     /// by the fold operation.
902     ///
903     /// The chief purpose of this function is to canonicalize regions so that two
904     /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
905     /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
906     /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
907     pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T>
908     where
909         T: TypeFoldable<'tcx>,
910     {
911         let mut counter = 0;
912         let inner = self
913             .replace_late_bound_regions(sig, |_| {
914                 let br = ty::BoundRegion {
915                     var: ty::BoundVar::from_u32(counter),
916                     kind: ty::BrAnon(counter),
917                 };
918                 let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
919                 counter += 1;
920                 r
921             })
922             .0;
923         let bound_vars = self.mk_bound_variable_kinds(
924             (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
925         );
926         Binder::bind_with_vars(inner, bound_vars)
927     }
928 }
929
930 pub struct ValidateBoundVars<'tcx> {
931     bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
932     binder_index: ty::DebruijnIndex,
933     // We may encounter the same variable at different levels of binding, so
934     // this can't just be `Ty`
935     visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
936 }
937
938 impl<'tcx> ValidateBoundVars<'tcx> {
939     pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
940         ValidateBoundVars {
941             bound_vars,
942             binder_index: ty::INNERMOST,
943             visited: SsoHashSet::default(),
944         }
945     }
946 }
947
948 impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
949     type BreakTy = ();
950
951     fn visit_binder<T: TypeFoldable<'tcx>>(
952         &mut self,
953         t: &Binder<'tcx, T>,
954     ) -> ControlFlow<Self::BreakTy> {
955         self.binder_index.shift_in(1);
956         let result = t.super_visit_with(self);
957         self.binder_index.shift_out(1);
958         result
959     }
960
961     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
962         if t.outer_exclusive_binder() < self.binder_index
963             || !self.visited.insert((self.binder_index, t))
964         {
965             return ControlFlow::BREAK;
966         }
967         match *t.kind() {
968             ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
969                 if self.bound_vars.len() <= bound_ty.var.as_usize() {
970                     bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
971                 }
972                 let list_var = self.bound_vars[bound_ty.var.as_usize()];
973                 match list_var {
974                     ty::BoundVariableKind::Ty(kind) => {
975                         if kind != bound_ty.kind {
976                             bug!(
977                                 "Mismatched type kinds: {:?} doesn't var in list {:?}",
978                                 bound_ty.kind,
979                                 list_var
980                             );
981                         }
982                     }
983                     _ => {
984                         bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var)
985                     }
986                 }
987             }
988
989             _ => (),
990         };
991
992         t.super_visit_with(self)
993     }
994
995     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
996         match *r {
997             ty::ReLateBound(index, br) if index == self.binder_index => {
998                 if self.bound_vars.len() <= br.var.as_usize() {
999                     bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars);
1000                 }
1001                 let list_var = self.bound_vars[br.var.as_usize()];
1002                 match list_var {
1003                     ty::BoundVariableKind::Region(kind) => {
1004                         if kind != br.kind {
1005                             bug!(
1006                                 "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
1007                                 br.kind,
1008                                 list_var,
1009                                 self.bound_vars
1010                             );
1011                         }
1012                     }
1013                     _ => bug!(
1014                         "Mismatched bound variable kinds! Expected region, found {:?}",
1015                         list_var
1016                     ),
1017                 }
1018             }
1019
1020             _ => (),
1021         };
1022
1023         r.super_visit_with(self)
1024     }
1025 }
1026
1027 ///////////////////////////////////////////////////////////////////////////
1028 // Shifter
1029 //
1030 // Shifts the De Bruijn indices on all escaping bound vars by a
1031 // fixed amount. Useful in substitution or when otherwise introducing
1032 // a binding level that is not intended to capture the existing bound
1033 // vars. See comment on `shift_vars_through_binders` method in
1034 // `subst.rs` for more details.
1035
1036 struct Shifter<'tcx> {
1037     tcx: TyCtxt<'tcx>,
1038     current_index: ty::DebruijnIndex,
1039     amount: u32,
1040 }
1041
1042 impl<'tcx> Shifter<'tcx> {
1043     pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self {
1044         Shifter { tcx, current_index: ty::INNERMOST, amount }
1045     }
1046 }
1047
1048 impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
1049     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
1050         self.tcx
1051     }
1052
1053     fn fold_binder<T: TypeFoldable<'tcx>>(
1054         &mut self,
1055         t: ty::Binder<'tcx, T>,
1056     ) -> ty::Binder<'tcx, T> {
1057         self.current_index.shift_in(1);
1058         let t = t.super_fold_with(self);
1059         self.current_index.shift_out(1);
1060         t
1061     }
1062
1063     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
1064         match *r {
1065             ty::ReLateBound(debruijn, br) => {
1066                 if self.amount == 0 || debruijn < self.current_index {
1067                     r
1068                 } else {
1069                     let debruijn = debruijn.shifted_in(self.amount);
1070                     let shifted = ty::ReLateBound(debruijn, br);
1071                     self.tcx.mk_region(shifted)
1072                 }
1073             }
1074             _ => r,
1075         }
1076     }
1077
1078     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1079         match *ty.kind() {
1080             ty::Bound(debruijn, bound_ty) => {
1081                 if self.amount == 0 || debruijn < self.current_index {
1082                     ty
1083                 } else {
1084                     let debruijn = debruijn.shifted_in(self.amount);
1085                     self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
1086                 }
1087             }
1088
1089             _ => ty.super_fold_with(self),
1090         }
1091     }
1092
1093     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1094         if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.val() {
1095             if self.amount == 0 || debruijn < self.current_index {
1096                 ct
1097             } else {
1098                 let debruijn = debruijn.shifted_in(self.amount);
1099                 self.tcx.mk_const(ty::ConstS {
1100                     val: ty::ConstKind::Bound(debruijn, bound_ct),
1101                     ty: ct.ty(),
1102                 })
1103             }
1104         } else {
1105             ct.super_fold_with(self)
1106         }
1107     }
1108 }
1109
1110 pub fn shift_region<'tcx>(
1111     tcx: TyCtxt<'tcx>,
1112     region: ty::Region<'tcx>,
1113     amount: u32,
1114 ) -> ty::Region<'tcx> {
1115     match *region {
1116         ty::ReLateBound(debruijn, br) if amount > 0 => {
1117             tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
1118         }
1119         _ => region,
1120     }
1121 }
1122
1123 pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
1124 where
1125     T: TypeFoldable<'tcx>,
1126 {
1127     debug!("shift_vars(value={:?}, amount={})", value, amount);
1128
1129     value.fold_with(&mut Shifter::new(tcx, amount))
1130 }
1131
1132 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
1133 struct FoundEscapingVars;
1134
1135 /// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
1136 /// bound region or a bound type.
1137 ///
1138 /// So, for example, consider a type like the following, which has two binders:
1139 ///
1140 ///    for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
1141 ///    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
1142 ///                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~  inner scope
1143 ///
1144 /// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
1145 /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
1146 /// fn type*, that type has an escaping region: `'a`.
1147 ///
1148 /// Note that what I'm calling an "escaping var" is often just called a "free var". However,
1149 /// we already use the term "free var". It refers to the regions or types that we use to represent
1150 /// bound regions or type params on a fn definition while we are type checking its body.
1151 ///
1152 /// To clarify, conceptually there is no particular difference between
1153 /// an "escaping" var and a "free" var. However, there is a big
1154 /// difference in practice. Basically, when "entering" a binding
1155 /// level, one is generally required to do some sort of processing to
1156 /// a bound var, such as replacing it with a fresh/placeholder
1157 /// var, or making an entry in the environment to represent the
1158 /// scope to which it is attached, etc. An escaping var represents
1159 /// a bound var for which this processing has not yet been done.
1160 struct HasEscapingVarsVisitor {
1161     /// Anything bound by `outer_index` or "above" is escaping.
1162     outer_index: ty::DebruijnIndex,
1163 }
1164
1165 impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
1166     type BreakTy = FoundEscapingVars;
1167
1168     fn visit_binder<T: TypeFoldable<'tcx>>(
1169         &mut self,
1170         t: &Binder<'tcx, T>,
1171     ) -> ControlFlow<Self::BreakTy> {
1172         self.outer_index.shift_in(1);
1173         let result = t.super_visit_with(self);
1174         self.outer_index.shift_out(1);
1175         result
1176     }
1177
1178     #[inline]
1179     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1180         // If the outer-exclusive-binder is *strictly greater* than
1181         // `outer_index`, that means that `t` contains some content
1182         // bound at `outer_index` or above (because
1183         // `outer_exclusive_binder` is always 1 higher than the
1184         // content in `t`). Therefore, `t` has some escaping vars.
1185         if t.outer_exclusive_binder() > self.outer_index {
1186             ControlFlow::Break(FoundEscapingVars)
1187         } else {
1188             ControlFlow::CONTINUE
1189         }
1190     }
1191
1192     #[inline]
1193     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1194         // If the region is bound by `outer_index` or anything outside
1195         // of outer index, then it escapes the binders we have
1196         // visited.
1197         if r.bound_at_or_above_binder(self.outer_index) {
1198             ControlFlow::Break(FoundEscapingVars)
1199         } else {
1200             ControlFlow::CONTINUE
1201         }
1202     }
1203
1204     fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
1205         // we don't have a `visit_infer_const` callback, so we have to
1206         // hook in here to catch this case (annoying...), but
1207         // otherwise we do want to remember to visit the rest of the
1208         // const, as it has types/regions embedded in a lot of other
1209         // places.
1210         match ct.val() {
1211             ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
1212                 ControlFlow::Break(FoundEscapingVars)
1213             }
1214             _ => ct.super_visit_with(self),
1215         }
1216     }
1217
1218     #[inline]
1219     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
1220         if predicate.outer_exclusive_binder() > self.outer_index {
1221             ControlFlow::Break(FoundEscapingVars)
1222         } else {
1223             ControlFlow::CONTINUE
1224         }
1225     }
1226 }
1227
1228 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
1229 struct FoundFlags;
1230
1231 // FIXME: Optimize for checking for infer flags
1232 struct HasTypeFlagsVisitor {
1233     flags: ty::TypeFlags,
1234 }
1235
1236 impl std::fmt::Debug for HasTypeFlagsVisitor {
1237     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1238         self.flags.fmt(fmt)
1239     }
1240 }
1241
1242 impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
1243     type BreakTy = FoundFlags;
1244
1245     #[inline]
1246     #[instrument(skip(self), level = "trace")]
1247     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1248         let flags = t.flags();
1249         trace!(t.flags=?t.flags());
1250         if flags.intersects(self.flags) {
1251             ControlFlow::Break(FoundFlags)
1252         } else {
1253             ControlFlow::CONTINUE
1254         }
1255     }
1256
1257     #[inline]
1258     #[instrument(skip(self), level = "trace")]
1259     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1260         let flags = r.type_flags();
1261         trace!(r.flags=?flags);
1262         if flags.intersects(self.flags) {
1263             ControlFlow::Break(FoundFlags)
1264         } else {
1265             ControlFlow::CONTINUE
1266         }
1267     }
1268
1269     #[inline]
1270     #[instrument(level = "trace")]
1271     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
1272         let flags = FlagComputation::for_const(c);
1273         trace!(r.flags=?flags);
1274         if flags.intersects(self.flags) {
1275             ControlFlow::Break(FoundFlags)
1276         } else {
1277             ControlFlow::CONTINUE
1278         }
1279     }
1280
1281     #[inline]
1282     #[instrument(level = "trace")]
1283     fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
1284         let flags = FlagComputation::for_unevaluated_const(uv);
1285         trace!(r.flags=?flags);
1286         if flags.intersects(self.flags) {
1287             ControlFlow::Break(FoundFlags)
1288         } else {
1289             ControlFlow::CONTINUE
1290         }
1291     }
1292
1293     #[inline]
1294     #[instrument(level = "trace")]
1295     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
1296         debug!(
1297             "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
1298             predicate,
1299             predicate.flags(),
1300             self.flags
1301         );
1302         if predicate.flags().intersects(self.flags) {
1303             ControlFlow::Break(FoundFlags)
1304         } else {
1305             ControlFlow::CONTINUE
1306         }
1307     }
1308 }
1309
1310 /// Collects all the late-bound regions at the innermost binding level
1311 /// into a hash set.
1312 struct LateBoundRegionsCollector {
1313     current_index: ty::DebruijnIndex,
1314     regions: FxHashSet<ty::BoundRegionKind>,
1315
1316     /// `true` if we only want regions that are known to be
1317     /// "constrained" when you equate this type with another type. In
1318     /// particular, if you have e.g., `&'a u32` and `&'b u32`, equating
1319     /// them constraints `'a == 'b`. But if you have `<&'a u32 as
1320     /// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those
1321     /// types may mean that `'a` and `'b` don't appear in the results,
1322     /// so they are not considered *constrained*.
1323     just_constrained: bool,
1324 }
1325
1326 impl LateBoundRegionsCollector {
1327     fn new(just_constrained: bool) -> Self {
1328         LateBoundRegionsCollector {
1329             current_index: ty::INNERMOST,
1330             regions: Default::default(),
1331             just_constrained,
1332         }
1333     }
1334 }
1335
1336 impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
1337     fn visit_binder<T: TypeFoldable<'tcx>>(
1338         &mut self,
1339         t: &Binder<'tcx, T>,
1340     ) -> ControlFlow<Self::BreakTy> {
1341         self.current_index.shift_in(1);
1342         let result = t.super_visit_with(self);
1343         self.current_index.shift_out(1);
1344         result
1345     }
1346
1347     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1348         // if we are only looking for "constrained" region, we have to
1349         // ignore the inputs to a projection, as they may not appear
1350         // in the normalized form
1351         if self.just_constrained {
1352             if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
1353                 return ControlFlow::CONTINUE;
1354             }
1355         }
1356
1357         t.super_visit_with(self)
1358     }
1359
1360     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
1361         // if we are only looking for "constrained" region, we have to
1362         // ignore the inputs of an unevaluated const, as they may not appear
1363         // in the normalized form
1364         if self.just_constrained {
1365             if let ty::ConstKind::Unevaluated(..) = c.val() {
1366                 return ControlFlow::CONTINUE;
1367             }
1368         }
1369
1370         c.super_visit_with(self)
1371     }
1372
1373     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1374         if let ty::ReLateBound(debruijn, br) = *r {
1375             if debruijn == self.current_index {
1376                 self.regions.insert(br.kind);
1377             }
1378         }
1379         ControlFlow::CONTINUE
1380     }
1381 }
1382
1383 /// Finds the max universe present
1384 pub struct MaxUniverse {
1385     max_universe: ty::UniverseIndex,
1386 }
1387
1388 impl MaxUniverse {
1389     pub fn new() -> Self {
1390         MaxUniverse { max_universe: ty::UniverseIndex::ROOT }
1391     }
1392
1393     pub fn max_universe(self) -> ty::UniverseIndex {
1394         self.max_universe
1395     }
1396 }
1397
1398 impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
1399     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1400         if let ty::Placeholder(placeholder) = t.kind() {
1401             self.max_universe = ty::UniverseIndex::from_u32(
1402                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
1403             );
1404         }
1405
1406         t.super_visit_with(self)
1407     }
1408
1409     fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
1410         if let ty::ConstKind::Placeholder(placeholder) = c.val() {
1411             self.max_universe = ty::UniverseIndex::from_u32(
1412                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
1413             );
1414         }
1415
1416         c.super_visit_with(self)
1417     }
1418
1419     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1420         if let ty::RePlaceholder(placeholder) = *r {
1421             self.max_universe = ty::UniverseIndex::from_u32(
1422                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
1423             );
1424         }
1425
1426         ControlFlow::CONTINUE
1427     }
1428 }