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