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