]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_resolve/src/late/lifetimes.rs
Use DefIdTree instead of open-coding it.
[rust.git] / compiler / rustc_resolve / src / late / lifetimes.rs
1 //! Resolution of early vs late bound lifetimes.
2 //!
3 //! Name resolution for lifetimes is performed on the AST and embedded into HIR.  From this
4 //! information, typechecking needs to transform the lifetime parameters into bound lifetimes.
5 //! Lifetimes can be early-bound or late-bound.  Construction of typechecking terms needs to visit
6 //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices.  This file
7 //! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
8
9 use rustc_ast::walk_list;
10 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
11 use rustc_errors::struct_span_err;
12 use rustc_hir as hir;
13 use rustc_hir::def::{DefKind, Res};
14 use rustc_hir::def_id::LocalDefId;
15 use rustc_hir::intravisit::{self, Visitor};
16 use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
17 use rustc_middle::bug;
18 use rustc_middle::hir::map::Map;
19 use rustc_middle::hir::nested_filter;
20 use rustc_middle::middle::resolve_lifetime::*;
21 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
22 use rustc_span::def_id::DefId;
23 use rustc_span::symbol::{sym, Ident};
24 use rustc_span::Span;
25 use std::fmt;
26
27 trait RegionExt {
28     fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
29
30     fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
31
32     fn id(&self) -> Option<DefId>;
33
34     fn shifted(self, amount: u32) -> Region;
35
36     fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
37 }
38
39 impl RegionExt for Region {
40     fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
41         let def_id = hir_map.local_def_id(param.hir_id);
42         debug!("Region::early: def_id={:?}", def_id);
43         (def_id, Region::EarlyBound(def_id.to_def_id()))
44     }
45
46     fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
47         let depth = ty::INNERMOST;
48         let def_id = hir_map.local_def_id(param.hir_id);
49         debug!(
50             "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
51             idx, param, depth, def_id,
52         );
53         (def_id, Region::LateBound(depth, idx, def_id.to_def_id()))
54     }
55
56     fn id(&self) -> Option<DefId> {
57         match *self {
58             Region::Static => None,
59
60             Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
61         }
62     }
63
64     fn shifted(self, amount: u32) -> Region {
65         match self {
66             Region::LateBound(debruijn, idx, id) => {
67                 Region::LateBound(debruijn.shifted_in(amount), idx, id)
68             }
69             _ => self,
70         }
71     }
72
73     fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region {
74         match self {
75             Region::LateBound(debruijn, index, id) => {
76                 Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id)
77             }
78             _ => self,
79         }
80     }
81 }
82
83 /// Maps the id of each lifetime reference to the lifetime decl
84 /// that it corresponds to.
85 ///
86 /// FIXME. This struct gets converted to a `ResolveLifetimes` for
87 /// actual use. It has the same data, but indexed by `LocalDefId`.  This
88 /// is silly.
89 #[derive(Debug, Default)]
90 struct NamedRegionMap {
91     // maps from every use of a named (not anonymous) lifetime to a
92     // `Region` describing how that region is bound
93     defs: HirIdMap<Region>,
94
95     // Maps relevant hir items to the bound vars on them. These include:
96     // - function defs
97     // - function pointers
98     // - closures
99     // - trait refs
100     // - bound types (like `T` in `for<'a> T<'a>: Foo`)
101     late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
102 }
103
104 pub(crate) struct LifetimeContext<'a, 'tcx> {
105     pub(crate) tcx: TyCtxt<'tcx>,
106     map: &'a mut NamedRegionMap,
107     scope: ScopeRef<'a>,
108
109     /// Indicates that we only care about the definition of a trait. This should
110     /// be false if the `Item` we are resolving lifetimes for is not a trait or
111     /// we eventually need lifetimes resolve for trait items.
112     trait_definition_only: bool,
113 }
114
115 #[derive(Debug)]
116 enum Scope<'a> {
117     /// Declares lifetimes, and each can be early-bound or late-bound.
118     /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
119     /// it should be shifted by the number of `Binder`s in between the
120     /// declaration `Binder` and the location it's referenced from.
121     Binder {
122         /// We use an IndexMap here because we want these lifetimes in order
123         /// for diagnostics.
124         lifetimes: FxIndexMap<LocalDefId, Region>,
125
126         scope_type: BinderScopeType,
127
128         /// The late bound vars for a given item are stored by `HirId` to be
129         /// queried later. However, if we enter an elision scope, we have to
130         /// later append the elided bound vars to the list and need to know what
131         /// to append to.
132         hir_id: hir::HirId,
133
134         s: ScopeRef<'a>,
135
136         /// If this binder comes from a where clause, specify how it was created.
137         /// This is used to diagnose inaccessible lifetimes in APIT:
138         /// ```ignore (illustrative)
139         /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
140         /// ```
141         where_bound_origin: Option<hir::PredicateOrigin>,
142     },
143
144     /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
145     /// if this is a fn body, otherwise the original definitions are used.
146     /// Unspecified lifetimes are inferred, unless an elision scope is nested,
147     /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
148     Body {
149         id: hir::BodyId,
150         s: ScopeRef<'a>,
151     },
152
153     /// A scope which either determines unspecified lifetimes or errors
154     /// on them (e.g., due to ambiguity).
155     Elision {
156         s: ScopeRef<'a>,
157     },
158
159     /// Use a specific lifetime (if `Some`) or leave it unset (to be
160     /// inferred in a function body or potentially error outside one),
161     /// for the default choice of lifetime in a trait object type.
162     ObjectLifetimeDefault {
163         lifetime: Option<Region>,
164         s: ScopeRef<'a>,
165     },
166
167     /// When we have nested trait refs, we concatenate late bound vars for inner
168     /// trait refs from outer ones. But we also need to include any HRTB
169     /// lifetimes encountered when identifying the trait that an associated type
170     /// is declared on.
171     Supertrait {
172         lifetimes: Vec<ty::BoundVariableKind>,
173         s: ScopeRef<'a>,
174     },
175
176     TraitRefBoundary {
177         s: ScopeRef<'a>,
178     },
179
180     Root,
181 }
182
183 #[derive(Copy, Clone, Debug)]
184 enum BinderScopeType {
185     /// Any non-concatenating binder scopes.
186     Normal,
187     /// Within a syntactic trait ref, there may be multiple poly trait refs that
188     /// are nested (under the `associated_type_bounds` feature). The binders of
189     /// the inner poly trait refs are extended from the outer poly trait refs
190     /// and don't increase the late bound depth. If you had
191     /// `T: for<'a>  Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope
192     /// would be `Concatenating`. This also used in trait refs in where clauses
193     /// where we have two binders `for<> T: for<> Foo` (I've intentionally left
194     /// out any lifetimes because they aren't needed to show the two scopes).
195     /// The inner `for<>` has a scope of `Concatenating`.
196     Concatenating,
197 }
198
199 // A helper struct for debugging scopes without printing parent scopes
200 struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
201
202 impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
203     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204         match self.0 {
205             Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
206                 .debug_struct("Binder")
207                 .field("lifetimes", lifetimes)
208                 .field("scope_type", scope_type)
209                 .field("hir_id", hir_id)
210                 .field("where_bound_origin", where_bound_origin)
211                 .field("s", &"..")
212                 .finish(),
213             Scope::Body { id, s: _ } => {
214                 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
215             }
216             Scope::Elision { s: _ } => f.debug_struct("Elision").field("s", &"..").finish(),
217             Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
218                 .debug_struct("ObjectLifetimeDefault")
219                 .field("lifetime", lifetime)
220                 .field("s", &"..")
221                 .finish(),
222             Scope::Supertrait { lifetimes, s: _ } => f
223                 .debug_struct("Supertrait")
224                 .field("lifetimes", lifetimes)
225                 .field("s", &"..")
226                 .finish(),
227             Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
228             Scope::Root => f.debug_struct("Root").finish(),
229         }
230     }
231 }
232
233 type ScopeRef<'a> = &'a Scope<'a>;
234
235 const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
236
237 pub fn provide(providers: &mut ty::query::Providers) {
238     *providers = ty::query::Providers {
239         resolve_lifetimes_trait_definition,
240         resolve_lifetimes,
241
242         named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
243         is_late_bound_map,
244         object_lifetime_default,
245         late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
246
247         ..*providers
248     };
249 }
250
251 /// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
252 /// Also does not generate any diagnostics.
253 ///
254 /// This is ultimately a subset of the `resolve_lifetimes` work. It effectively
255 /// resolves lifetimes only within the trait "header" -- that is, the trait
256 /// and supertrait list. In contrast, `resolve_lifetimes` resolves all the
257 /// lifetimes within the trait and its items. There is room to refactor this,
258 /// for example to resolve lifetimes for each trait item in separate queries,
259 /// but it's convenient to do the entire trait at once because the lifetimes
260 /// from the trait definition are in scope within the trait items as well.
261 ///
262 /// The reason for this separate call is to resolve what would otherwise
263 /// be a cycle. Consider this example:
264 ///
265 /// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub)
266 /// trait Base<'a> {
267 ///     type BaseItem;
268 /// }
269 /// trait Sub<'b>: for<'a> Base<'a> {
270 ///    type SubItem: Sub<BaseItem = &'b u32>;
271 /// }
272 /// ```
273 ///
274 /// When we resolve `Sub` and all its items, we also have to resolve `Sub<BaseItem = &'b u32>`.
275 /// To figure out the index of `'b`, we have to know about the supertraits
276 /// of `Sub` so that we can determine that the `for<'a>` will be in scope.
277 /// (This is because we -- currently at least -- flatten all the late-bound
278 /// lifetimes into a single binder.) This requires us to resolve the
279 /// *trait definition* of `Sub`; basically just enough lifetime information
280 /// to look at the supertraits.
281 #[tracing::instrument(level = "debug", skip(tcx))]
282 fn resolve_lifetimes_trait_definition(
283     tcx: TyCtxt<'_>,
284     local_def_id: LocalDefId,
285 ) -> ResolveLifetimes {
286     convert_named_region_map(do_resolve(tcx, local_def_id, true))
287 }
288
289 /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
290 /// You should not read the result of this query directly, but rather use
291 /// `named_region_map`, `is_late_bound_map`, etc.
292 #[tracing::instrument(level = "debug", skip(tcx))]
293 fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
294     convert_named_region_map(do_resolve(tcx, local_def_id, false))
295 }
296
297 fn do_resolve(
298     tcx: TyCtxt<'_>,
299     local_def_id: LocalDefId,
300     trait_definition_only: bool,
301 ) -> NamedRegionMap {
302     let item = tcx.hir().expect_item(local_def_id);
303     let mut named_region_map =
304         NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
305     let mut visitor = LifetimeContext {
306         tcx,
307         map: &mut named_region_map,
308         scope: ROOT_SCOPE,
309         trait_definition_only,
310     };
311     visitor.visit_item(item);
312
313     named_region_map
314 }
315
316 fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
317     let mut rl = ResolveLifetimes::default();
318
319     for (hir_id, v) in named_region_map.defs {
320         let map = rl.defs.entry(hir_id.owner).or_default();
321         map.insert(hir_id.local_id, v);
322     }
323     for (hir_id, v) in named_region_map.late_bound_vars {
324         let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
325         map.insert(hir_id.local_id, v);
326     }
327
328     debug!(?rl.defs);
329     rl
330 }
331
332 /// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
333 /// There are two important things this does.
334 /// First, we have to resolve lifetimes for
335 /// the entire *`Item`* that contains this owner, because that's the largest "scope"
336 /// where we can have relevant lifetimes.
337 /// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
338 /// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
339 /// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
340 /// other than the trait itself (like the trait methods or associated types), then we just use the regular
341 /// `resolve_lifetimes`.
342 fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes {
343     let item_id = item_for(tcx, def_id);
344     if item_id == def_id {
345         let item = tcx.hir().item(hir::ItemId { def_id: item_id });
346         match item.kind {
347             hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id),
348             _ => tcx.resolve_lifetimes(item_id),
349         }
350     } else {
351         tcx.resolve_lifetimes(item_id)
352     }
353 }
354
355 /// Finds the `Item` that contains the given `LocalDefId`
356 fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
357     match tcx.hir().find_by_def_id(local_def_id) {
358         Some(Node::Item(item)) => {
359             return item.def_id;
360         }
361         _ => {}
362     }
363     let item = {
364         let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
365         let mut parent_iter = tcx.hir().parent_iter(hir_id);
366         loop {
367             let node = parent_iter.next().map(|n| n.1);
368             match node {
369                 Some(hir::Node::Item(item)) => break item.def_id,
370                 Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."),
371                 _ => {}
372             }
373         }
374     };
375     item
376 }
377
378 fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
379     match region {
380         Region::LateBound(_, _, def_id) => {
381             let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
382             ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
383         }
384         _ => bug!("{:?} is not a late region", region),
385     }
386 }
387
388 impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
389     /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
390     fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
391         let mut scope = self.scope;
392         let mut supertrait_lifetimes = vec![];
393         loop {
394             match scope {
395                 Scope::Body { .. } | Scope::Root => {
396                     break (vec![], BinderScopeType::Normal);
397                 }
398
399                 Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
400                     scope = s;
401                 }
402
403                 Scope::Supertrait { s, lifetimes } => {
404                     supertrait_lifetimes = lifetimes.clone();
405                     scope = s;
406                 }
407
408                 Scope::TraitRefBoundary { .. } => {
409                     // We should only see super trait lifetimes if there is a `Binder` above
410                     assert!(supertrait_lifetimes.is_empty());
411                     break (vec![], BinderScopeType::Normal);
412                 }
413
414                 Scope::Binder { hir_id, .. } => {
415                     // Nested poly trait refs have the binders concatenated
416                     let mut full_binders =
417                         self.map.late_bound_vars.entry(*hir_id).or_default().clone();
418                     full_binders.extend(supertrait_lifetimes.into_iter());
419                     break (full_binders, BinderScopeType::Concatenating);
420                 }
421             }
422         }
423     }
424 }
425 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
426     type NestedFilter = nested_filter::All;
427
428     fn nested_visit_map(&mut self) -> Self::Map {
429         self.tcx.hir()
430     }
431
432     // We want to nest trait/impl items in their parent, but nothing else.
433     fn visit_nested_item(&mut self, _: hir::ItemId) {}
434
435     fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) {
436         if !self.trait_definition_only {
437             intravisit::walk_trait_item_ref(self, ii)
438         }
439     }
440
441     fn visit_nested_body(&mut self, body: hir::BodyId) {
442         let body = self.tcx.hir().body(body);
443         self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
444             this.visit_body(body);
445         });
446     }
447
448     fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
449         if let hir::ExprKind::Closure(hir::Closure {
450             binder, bound_generic_params, fn_decl, ..
451         }) = e.kind
452         {
453             if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
454                 fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
455                     struct V(Option<Span>);
456
457                     impl<'v> Visitor<'v> for V {
458                         fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
459                             match t.kind {
460                                 _ if self.0.is_some() => (),
461                                 hir::TyKind::Infer => {
462                                     self.0 = Some(t.span);
463                                 }
464                                 _ => intravisit::walk_ty(self, t),
465                             }
466                         }
467                     }
468
469                     let mut v = V(None);
470                     v.visit_ty(ty);
471                     v.0
472                 }
473
474                 let infer_in_rt_sp = match fn_decl.output {
475                     hir::FnRetTy::DefaultReturn(sp) => Some(sp),
476                     hir::FnRetTy::Return(ty) => span_of_infer(ty),
477                 };
478
479                 let infer_spans = fn_decl
480                     .inputs
481                     .into_iter()
482                     .filter_map(span_of_infer)
483                     .chain(infer_in_rt_sp)
484                     .collect::<Vec<_>>();
485
486                 if !infer_spans.is_empty() {
487                     self.tcx.sess
488                         .struct_span_err(
489                             infer_spans,
490                             "implicit types in closure signatures are forbidden when `for<...>` is present",
491                         )
492                         .span_label(for_sp, "`for<...>` is here")
493                         .emit();
494                 }
495             }
496
497             let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
498                 bound_generic_params
499                     .iter()
500                     .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
501                     .enumerate()
502                     .map(|(late_bound_idx, param)| {
503                         let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
504                         let r = late_region_as_bound_region(self.tcx, &pair.1);
505                         (pair, r)
506                     })
507                     .unzip();
508
509             self.map.late_bound_vars.insert(e.hir_id, binders);
510             let scope = Scope::Binder {
511                 hir_id: e.hir_id,
512                 lifetimes,
513                 s: self.scope,
514                 scope_type: BinderScopeType::Normal,
515                 where_bound_origin: None,
516             };
517
518             self.with(scope, |this| {
519                 // a closure has no bounds, so everything
520                 // contained within is scoped within its binder.
521                 intravisit::walk_expr(this, e)
522             });
523         } else {
524             intravisit::walk_expr(self, e)
525         }
526     }
527
528     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
529         match &item.kind {
530             hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
531                 if let Some(of_trait) = of_trait {
532                     self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default());
533                 }
534             }
535             _ => {}
536         }
537         match item.kind {
538             hir::ItemKind::Fn(_, ref generics, _) => {
539                 self.visit_early_late(item.hir_id(), generics, |this| {
540                     intravisit::walk_item(this, item);
541                 });
542             }
543
544             hir::ItemKind::ExternCrate(_)
545             | hir::ItemKind::Use(..)
546             | hir::ItemKind::Macro(..)
547             | hir::ItemKind::Mod(..)
548             | hir::ItemKind::ForeignMod { .. }
549             | hir::ItemKind::GlobalAsm(..) => {
550                 // These sorts of items have no lifetime parameters at all.
551                 intravisit::walk_item(self, item);
552             }
553             hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
554                 // No lifetime parameters, but implied 'static.
555                 self.with(Scope::Elision { s: self.scope }, |this| {
556                     intravisit::walk_item(this, item)
557                 });
558             }
559             hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
560                 // Opaque types are visited when we visit the
561                 // `TyKind::OpaqueDef`, so that they have the lifetimes from
562                 // their parent opaque_ty in scope.
563                 //
564                 // The core idea here is that since OpaqueTys are generated with the impl Trait as
565                 // their owner, we can keep going until we find the Item that owns that. We then
566                 // conservatively add all resolved lifetimes. Otherwise we run into problems in
567                 // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
568                 for (_hir_id, node) in
569                     self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id))
570                 {
571                     match node {
572                         hir::Node::Item(parent_item) => {
573                             let resolved_lifetimes: &ResolveLifetimes =
574                                 self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id));
575                             // We need to add *all* deps, since opaque tys may want them from *us*
576                             for (&owner, defs) in resolved_lifetimes.defs.iter() {
577                                 defs.iter().for_each(|(&local_id, region)| {
578                                     self.map.defs.insert(hir::HirId { owner, local_id }, *region);
579                                 });
580                             }
581                             for (&owner, late_bound_vars) in
582                                 resolved_lifetimes.late_bound_vars.iter()
583                             {
584                                 late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
585                                     self.map.late_bound_vars.insert(
586                                         hir::HirId { owner, local_id },
587                                         late_bound_vars.clone(),
588                                     );
589                                 });
590                             }
591                             break;
592                         }
593                         hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"),
594                         _ => {}
595                     }
596                 }
597             }
598             hir::ItemKind::TyAlias(_, ref generics)
599             | hir::ItemKind::Enum(_, ref generics)
600             | hir::ItemKind::Struct(_, ref generics)
601             | hir::ItemKind::Union(_, ref generics)
602             | hir::ItemKind::Trait(_, _, ref generics, ..)
603             | hir::ItemKind::TraitAlias(ref generics, ..)
604             | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
605                 // These kinds of items have only early-bound lifetime parameters.
606                 let lifetimes = generics
607                     .params
608                     .iter()
609                     .filter_map(|param| match param.kind {
610                         GenericParamKind::Lifetime { .. } => {
611                             Some(Region::early(self.tcx.hir(), param))
612                         }
613                         GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
614                     })
615                     .collect();
616                 self.map.late_bound_vars.insert(item.hir_id(), vec![]);
617                 let scope = Scope::Binder {
618                     hir_id: item.hir_id(),
619                     lifetimes,
620                     scope_type: BinderScopeType::Normal,
621                     s: ROOT_SCOPE,
622                     where_bound_origin: None,
623                 };
624                 self.with(scope, |this| {
625                     let scope = Scope::TraitRefBoundary { s: this.scope };
626                     this.with(scope, |this| {
627                         intravisit::walk_item(this, item);
628                     });
629                 });
630             }
631         }
632     }
633
634     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
635         match item.kind {
636             hir::ForeignItemKind::Fn(_, _, ref generics) => {
637                 self.visit_early_late(item.hir_id(), generics, |this| {
638                     intravisit::walk_foreign_item(this, item);
639                 })
640             }
641             hir::ForeignItemKind::Static(..) => {
642                 intravisit::walk_foreign_item(self, item);
643             }
644             hir::ForeignItemKind::Type => {
645                 intravisit::walk_foreign_item(self, item);
646             }
647         }
648     }
649
650     #[tracing::instrument(level = "debug", skip(self))]
651     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
652         match ty.kind {
653             hir::TyKind::BareFn(ref c) => {
654                 let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
655                     .generic_params
656                     .iter()
657                     .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
658                     .enumerate()
659                     .map(|(late_bound_idx, param)| {
660                         let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
661                         let r = late_region_as_bound_region(self.tcx, &pair.1);
662                         (pair, r)
663                     })
664                     .unzip();
665                 self.map.late_bound_vars.insert(ty.hir_id, binders);
666                 let scope = Scope::Binder {
667                     hir_id: ty.hir_id,
668                     lifetimes,
669                     s: self.scope,
670                     scope_type: BinderScopeType::Normal,
671                     where_bound_origin: None,
672                 };
673                 self.with(scope, |this| {
674                     // a bare fn has no bounds, so everything
675                     // contained within is scoped within its binder.
676                     intravisit::walk_ty(this, ty);
677                 });
678             }
679             hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
680                 debug!(?bounds, ?lifetime, "TraitObject");
681                 let scope = Scope::TraitRefBoundary { s: self.scope };
682                 self.with(scope, |this| {
683                     for bound in bounds {
684                         this.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
685                     }
686                 });
687                 match lifetime.name {
688                     LifetimeName::ImplicitObjectLifetimeDefault => {
689                         // If the user does not write *anything*, we
690                         // use the object lifetime defaulting
691                         // rules. So e.g., `Box<dyn Debug>` becomes
692                         // `Box<dyn Debug + 'static>`.
693                         self.resolve_object_lifetime_default(lifetime)
694                     }
695                     LifetimeName::Infer => {
696                         // If the user writes `'_`, we use the *ordinary* elision
697                         // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
698                         // resolved the same as the `'_` in `&'_ Foo`.
699                         //
700                         // cc #48468
701                     }
702                     LifetimeName::Param(..) | LifetimeName::Static => {
703                         // If the user wrote an explicit name, use that.
704                         self.visit_lifetime(lifetime);
705                     }
706                     LifetimeName::Error => {}
707                 }
708             }
709             hir::TyKind::Rptr(ref lifetime_ref, ref mt) => {
710                 self.visit_lifetime(lifetime_ref);
711                 let scope = Scope::ObjectLifetimeDefault {
712                     lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(),
713                     s: self.scope,
714                 };
715                 self.with(scope, |this| this.visit_ty(&mt.ty));
716             }
717             hir::TyKind::OpaqueDef(item_id, lifetimes) => {
718                 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
719                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
720                 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
721                 //                 ^                  ^ this gets resolved in the scope of
722                 //                                      the opaque_ty generics
723                 let opaque_ty = self.tcx.hir().item(item_id);
724                 let (generics, bounds) = match opaque_ty.kind {
725                     hir::ItemKind::OpaqueTy(hir::OpaqueTy {
726                         origin: hir::OpaqueTyOrigin::TyAlias,
727                         ..
728                     }) => {
729                         intravisit::walk_ty(self, ty);
730
731                         // Elided lifetimes are not allowed in non-return
732                         // position impl Trait
733                         let scope = Scope::TraitRefBoundary { s: self.scope };
734                         self.with(scope, |this| {
735                             let scope = Scope::Elision { s: this.scope };
736                             this.with(scope, |this| {
737                                 intravisit::walk_item(this, opaque_ty);
738                             })
739                         });
740
741                         return;
742                     }
743                     hir::ItemKind::OpaqueTy(hir::OpaqueTy {
744                         origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
745                         ref generics,
746                         bounds,
747                         ..
748                     }) => (generics, bounds),
749                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
750                 };
751
752                 // Resolve the lifetimes that are applied to the opaque type.
753                 // These are resolved in the current scope.
754                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
755                 // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
756                 //          ^                 ^this gets resolved in the current scope
757                 for lifetime in lifetimes {
758                     let hir::GenericArg::Lifetime(lifetime) = lifetime else {
759                         continue
760                     };
761                     self.visit_lifetime(lifetime);
762
763                     // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
764                     // and ban them. Type variables instantiated inside binders aren't
765                     // well-supported at the moment, so this doesn't work.
766                     // In the future, this should be fixed and this error should be removed.
767                     let def = self.map.defs.get(&lifetime.hir_id).cloned();
768                     let Some(Region::LateBound(_, _, def_id)) = def else {
769                         continue
770                     };
771                     let Some(def_id) = def_id.as_local() else {
772                         continue
773                     };
774                     let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
775                     // Ensure that the parent of the def is an item, not HRTB
776                     let parent_id = self.tcx.hir().get_parent_node(hir_id);
777                     if !parent_id.is_owner() {
778                         if !self.trait_definition_only {
779                             struct_span_err!(
780                                 self.tcx.sess,
781                                 lifetime.span,
782                                 E0657,
783                                 "`impl Trait` can only capture lifetimes \
784                                     bound at the fn or impl level"
785                             )
786                             .emit();
787                         }
788                         self.uninsert_lifetime_on_error(lifetime, def.unwrap());
789                     }
790                     if let hir::Node::Item(hir::Item {
791                         kind: hir::ItemKind::OpaqueTy { .. }, ..
792                     }) = self.tcx.hir().get(parent_id)
793                     {
794                         if !self.trait_definition_only {
795                             let mut err = self.tcx.sess.struct_span_err(
796                                 lifetime.span,
797                                 "higher kinded lifetime bounds on nested opaque types are not supported yet",
798                             );
799                             err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
800                             err.emit();
801                         }
802                         self.uninsert_lifetime_on_error(lifetime, def.unwrap());
803                     }
804                 }
805
806                 // We want to start our early-bound indices at the end of the parent scope,
807                 // not including any parent `impl Trait`s.
808                 let mut lifetimes = FxIndexMap::default();
809                 debug!(?generics.params);
810                 for param in generics.params {
811                     match param.kind {
812                         GenericParamKind::Lifetime { .. } => {
813                             let (def_id, reg) = Region::early(self.tcx.hir(), &param);
814                             lifetimes.insert(def_id, reg);
815                         }
816                         GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
817                     }
818                 }
819                 self.map.late_bound_vars.insert(ty.hir_id, vec![]);
820
821                 let scope = Scope::Binder {
822                     hir_id: ty.hir_id,
823                     lifetimes,
824                     s: self.scope,
825                     scope_type: BinderScopeType::Normal,
826                     where_bound_origin: None,
827                 };
828                 self.with(scope, |this| {
829                     let scope = Scope::TraitRefBoundary { s: this.scope };
830                     this.with(scope, |this| {
831                         this.visit_generics(generics);
832                         for bound in bounds {
833                             this.visit_param_bound(bound);
834                         }
835                     })
836                 });
837             }
838             _ => intravisit::walk_ty(self, ty),
839         }
840     }
841
842     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
843         use self::hir::TraitItemKind::*;
844         match trait_item.kind {
845             Fn(_, _) => {
846                 self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| {
847                     intravisit::walk_trait_item(this, trait_item)
848                 });
849             }
850             Type(bounds, ref ty) => {
851                 let generics = &trait_item.generics;
852                 let lifetimes = generics
853                     .params
854                     .iter()
855                     .filter_map(|param| match param.kind {
856                         GenericParamKind::Lifetime { .. } => {
857                             Some(Region::early(self.tcx.hir(), param))
858                         }
859                         GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
860                     })
861                     .collect();
862                 self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
863                 let scope = Scope::Binder {
864                     hir_id: trait_item.hir_id(),
865                     lifetimes,
866                     s: self.scope,
867                     scope_type: BinderScopeType::Normal,
868                     where_bound_origin: None,
869                 };
870                 self.with(scope, |this| {
871                     let scope = Scope::TraitRefBoundary { s: this.scope };
872                     this.with(scope, |this| {
873                         this.visit_generics(generics);
874                         for bound in bounds {
875                             this.visit_param_bound(bound);
876                         }
877                         if let Some(ty) = ty {
878                             this.visit_ty(ty);
879                         }
880                     })
881                 });
882             }
883             Const(_, _) => {
884                 // Only methods and types support generics.
885                 assert!(trait_item.generics.params.is_empty());
886                 intravisit::walk_trait_item(self, trait_item);
887             }
888         }
889     }
890
891     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
892         use self::hir::ImplItemKind::*;
893         match impl_item.kind {
894             Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
895                 intravisit::walk_impl_item(this, impl_item)
896             }),
897             TyAlias(ref ty) => {
898                 let generics = &impl_item.generics;
899                 let lifetimes: FxIndexMap<LocalDefId, Region> = generics
900                     .params
901                     .iter()
902                     .filter_map(|param| match param.kind {
903                         GenericParamKind::Lifetime { .. } => {
904                             Some(Region::early(self.tcx.hir(), param))
905                         }
906                         GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
907                     })
908                     .collect();
909                 self.map.late_bound_vars.insert(ty.hir_id, vec![]);
910                 let scope = Scope::Binder {
911                     hir_id: ty.hir_id,
912                     lifetimes,
913                     s: self.scope,
914                     scope_type: BinderScopeType::Normal,
915                     where_bound_origin: None,
916                 };
917                 self.with(scope, |this| {
918                     let scope = Scope::TraitRefBoundary { s: this.scope };
919                     this.with(scope, |this| {
920                         this.visit_generics(generics);
921                         this.visit_ty(ty);
922                     })
923                 });
924             }
925             Const(_, _) => {
926                 // Only methods and types support generics.
927                 assert!(impl_item.generics.params.is_empty());
928                 intravisit::walk_impl_item(self, impl_item);
929             }
930         }
931     }
932
933     #[tracing::instrument(level = "debug", skip(self))]
934     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
935         match lifetime_ref.name {
936             hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
937             hir::LifetimeName::Param(param_def_id, _) => {
938                 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
939             }
940             // If we've already reported an error, just ignore `lifetime_ref`.
941             hir::LifetimeName::Error => {}
942             // Those will be resolved by typechecking.
943             hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {}
944         }
945     }
946
947     fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) {
948         for (i, segment) in path.segments.iter().enumerate() {
949             let depth = path.segments.len() - i - 1;
950             if let Some(ref args) = segment.args {
951                 self.visit_segment_args(path.res, depth, args);
952             }
953         }
954     }
955
956     fn visit_fn(
957         &mut self,
958         fk: intravisit::FnKind<'tcx>,
959         fd: &'tcx hir::FnDecl<'tcx>,
960         body_id: hir::BodyId,
961         _: Span,
962         _: hir::HirId,
963     ) {
964         let output = match fd.output {
965             hir::FnRetTy::DefaultReturn(_) => None,
966             hir::FnRetTy::Return(ref ty) => Some(&**ty),
967         };
968         self.visit_fn_like_elision(&fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
969         intravisit::walk_fn_kind(self, fk);
970         self.visit_nested_body(body_id)
971     }
972
973     fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
974         let scope = Scope::TraitRefBoundary { s: self.scope };
975         self.with(scope, |this| {
976             for param in generics.params {
977                 match param.kind {
978                     GenericParamKind::Lifetime { .. } => {}
979                     GenericParamKind::Type { ref default, .. } => {
980                         if let Some(ref ty) = default {
981                             this.visit_ty(&ty);
982                         }
983                     }
984                     GenericParamKind::Const { ref ty, default } => {
985                         this.visit_ty(&ty);
986                         if let Some(default) = default {
987                             this.visit_body(this.tcx.hir().body(default.body));
988                         }
989                     }
990                 }
991             }
992             for predicate in generics.predicates {
993                 match predicate {
994                     &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
995                         ref bounded_ty,
996                         bounds,
997                         ref bound_generic_params,
998                         origin,
999                         ..
1000                     }) => {
1001                         let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
1002                             bound_generic_params
1003                                 .iter()
1004                                 .filter(|param| {
1005                                     matches!(param.kind, GenericParamKind::Lifetime { .. })
1006                                 })
1007                                 .enumerate()
1008                                 .map(|(late_bound_idx, param)| {
1009                                     let pair =
1010                                         Region::late(late_bound_idx as u32, this.tcx.hir(), param);
1011                                     let r = late_region_as_bound_region(this.tcx, &pair.1);
1012                                     (pair, r)
1013                                 })
1014                                 .unzip();
1015                         this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
1016                         // Even if there are no lifetimes defined here, we still wrap it in a binder
1017                         // scope. If there happens to be a nested poly trait ref (an error), that
1018                         // will be `Concatenating` anyways, so we don't have to worry about the depth
1019                         // being wrong.
1020                         let scope = Scope::Binder {
1021                             hir_id: bounded_ty.hir_id,
1022                             lifetimes,
1023                             s: this.scope,
1024                             scope_type: BinderScopeType::Normal,
1025                             where_bound_origin: Some(origin),
1026                         };
1027                         this.with(scope, |this| {
1028                             this.visit_ty(&bounded_ty);
1029                             walk_list!(this, visit_param_bound, bounds);
1030                         })
1031                     }
1032                     &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
1033                         ref lifetime,
1034                         bounds,
1035                         ..
1036                     }) => {
1037                         this.visit_lifetime(lifetime);
1038                         walk_list!(this, visit_param_bound, bounds);
1039
1040                         if lifetime.name != hir::LifetimeName::Static {
1041                             for bound in bounds {
1042                                 let hir::GenericBound::Outlives(ref lt) = bound else {
1043                                     continue;
1044                                 };
1045                                 if lt.name != hir::LifetimeName::Static {
1046                                     continue;
1047                                 }
1048                                 this.insert_lifetime(lt, Region::Static);
1049                                 this.tcx
1050                                     .sess
1051                                     .struct_span_warn(
1052                                         lifetime.span,
1053                                         &format!(
1054                                             "unnecessary lifetime parameter `{}`",
1055                                             lifetime.name.ident(),
1056                                         ),
1057                                     )
1058                                     .help(&format!(
1059                                         "you can use the `'static` lifetime directly, in place of `{}`",
1060                                         lifetime.name.ident(),
1061                                     ))
1062                                     .emit();
1063                             }
1064                         }
1065                     }
1066                     &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
1067                         ref lhs_ty,
1068                         ref rhs_ty,
1069                         ..
1070                     }) => {
1071                         this.visit_ty(lhs_ty);
1072                         this.visit_ty(rhs_ty);
1073                     }
1074                 }
1075             }
1076         })
1077     }
1078
1079     fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
1080         match bound {
1081             hir::GenericBound::LangItemTrait(_, _, hir_id, _) => {
1082                 // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go
1083                 // through the regular poly trait ref code, so we don't get another
1084                 // chance to introduce a binder. For now, I'm keeping the existing logic
1085                 // of "if there isn't a Binder scope above us, add one", but I
1086                 // imagine there's a better way to go about this.
1087                 let (binders, scope_type) = self.poly_trait_ref_binder_info();
1088
1089                 self.map.late_bound_vars.insert(*hir_id, binders);
1090                 let scope = Scope::Binder {
1091                     hir_id: *hir_id,
1092                     lifetimes: FxIndexMap::default(),
1093                     s: self.scope,
1094                     scope_type,
1095                     where_bound_origin: None,
1096                 };
1097                 self.with(scope, |this| {
1098                     intravisit::walk_param_bound(this, bound);
1099                 });
1100             }
1101             _ => intravisit::walk_param_bound(self, bound),
1102         }
1103     }
1104
1105     fn visit_poly_trait_ref(
1106         &mut self,
1107         trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
1108         _modifier: hir::TraitBoundModifier,
1109     ) {
1110         debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
1111
1112         let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
1113
1114         let initial_bound_vars = binders.len() as u32;
1115         let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
1116         let binders_iter = trait_ref
1117             .bound_generic_params
1118             .iter()
1119             .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
1120             .enumerate()
1121             .map(|(late_bound_idx, param)| {
1122                 let pair =
1123                     Region::late(initial_bound_vars + late_bound_idx as u32, self.tcx.hir(), param);
1124                 let r = late_region_as_bound_region(self.tcx, &pair.1);
1125                 lifetimes.insert(pair.0, pair.1);
1126                 r
1127             });
1128         binders.extend(binders_iter);
1129
1130         debug!(?binders);
1131         self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
1132
1133         // Always introduce a scope here, even if this is in a where clause and
1134         // we introduced the binders around the bounded Ty. In that case, we
1135         // just reuse the concatenation functionality also present in nested trait
1136         // refs.
1137         let scope = Scope::Binder {
1138             hir_id: trait_ref.trait_ref.hir_ref_id,
1139             lifetimes,
1140             s: self.scope,
1141             scope_type,
1142             where_bound_origin: None,
1143         };
1144         self.with(scope, |this| {
1145             walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
1146             this.visit_trait_ref(&trait_ref.trait_ref);
1147         });
1148     }
1149 }
1150
1151 fn object_lifetime_default<'tcx>(
1152     tcx: TyCtxt<'tcx>,
1153     param_def_id: DefId,
1154 ) -> Option<ObjectLifetimeDefault> {
1155     let param_def_id = param_def_id.expect_local();
1156     let parent_def_id = tcx.local_parent(param_def_id);
1157     let generics = tcx.hir().get_generics(parent_def_id)?;
1158     let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1159     let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?;
1160
1161     // Scan the bounds and where-clauses on parameters to extract bounds
1162     // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1163     // for each type parameter.
1164     match param.kind {
1165         GenericParamKind::Lifetime { .. } => None,
1166         GenericParamKind::Type { .. } => {
1167             let mut set = Set1::Empty;
1168
1169             // Look for `type: ...` where clauses.
1170             for bound in generics.bounds_for_param(param_def_id) {
1171                 // Ignore `for<'a> type: ...` as they can change what
1172                 // lifetimes mean (although we could "just" handle it).
1173                 if !bound.bound_generic_params.is_empty() {
1174                     continue;
1175                 }
1176
1177                 for bound in bound.bounds {
1178                     if let hir::GenericBound::Outlives(ref lifetime) = *bound {
1179                         set.insert(lifetime.name.normalize_to_macros_2_0());
1180                     }
1181                 }
1182             }
1183
1184             Some(match set {
1185                 Set1::Empty => ObjectLifetimeDefault::Empty,
1186                 Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
1187                 Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
1188                     ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1189                 }
1190                 _ => ObjectLifetimeDefault::Ambiguous,
1191             })
1192         }
1193         GenericParamKind::Const { .. } => {
1194             // Generic consts don't impose any constraints.
1195             //
1196             // We still store a dummy value here to allow generic parameters
1197             // in an arbitrary order.
1198             Some(ObjectLifetimeDefault::Empty)
1199         }
1200     }
1201 }
1202
1203 impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1204     fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1205     where
1206         F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
1207     {
1208         let LifetimeContext { tcx, map, .. } = self;
1209         let mut this = LifetimeContext {
1210             tcx: *tcx,
1211             map,
1212             scope: &wrap_scope,
1213             trait_definition_only: self.trait_definition_only,
1214         };
1215         let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
1216         {
1217             let _enter = span.enter();
1218             f(&mut this);
1219         }
1220     }
1221
1222     /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1223     ///
1224     /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1225     /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1226     /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1227     ///
1228     /// For example:
1229     ///
1230     ///    fn foo<'a,'b,'c,T:Trait<'b>>(...)
1231     ///
1232     /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1233     /// lifetimes may be interspersed together.
1234     ///
1235     /// If early bound lifetimes are present, we separate them into their own list (and likewise
1236     /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1237     /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1238     /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1239     /// ordering is not important there.
1240     fn visit_early_late<F>(
1241         &mut self,
1242         hir_id: hir::HirId,
1243         generics: &'tcx hir::Generics<'tcx>,
1244         walk: F,
1245     ) where
1246         F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
1247     {
1248         let mut named_late_bound_vars = 0;
1249         let lifetimes: FxIndexMap<LocalDefId, Region> = generics
1250             .params
1251             .iter()
1252             .filter_map(|param| match param.kind {
1253                 GenericParamKind::Lifetime { .. } => {
1254                     if self.tcx.is_late_bound(param.hir_id) {
1255                         let late_bound_idx = named_late_bound_vars;
1256                         named_late_bound_vars += 1;
1257                         Some(Region::late(late_bound_idx, self.tcx.hir(), param))
1258                     } else {
1259                         Some(Region::early(self.tcx.hir(), param))
1260                     }
1261                 }
1262                 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
1263             })
1264             .collect();
1265
1266         let binders: Vec<_> = generics
1267             .params
1268             .iter()
1269             .filter(|param| {
1270                 matches!(param.kind, GenericParamKind::Lifetime { .. })
1271                     && self.tcx.is_late_bound(param.hir_id)
1272             })
1273             .enumerate()
1274             .map(|(late_bound_idx, param)| {
1275                 let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
1276                 late_region_as_bound_region(self.tcx, &pair.1)
1277             })
1278             .collect();
1279         self.map.late_bound_vars.insert(hir_id, binders);
1280         let scope = Scope::Binder {
1281             hir_id,
1282             lifetimes,
1283             s: self.scope,
1284             scope_type: BinderScopeType::Normal,
1285             where_bound_origin: None,
1286         };
1287         self.with(scope, walk);
1288     }
1289
1290     #[tracing::instrument(level = "debug", skip(self))]
1291     fn resolve_lifetime_ref(
1292         &mut self,
1293         region_def_id: LocalDefId,
1294         lifetime_ref: &'tcx hir::Lifetime,
1295     ) {
1296         // Walk up the scope chain, tracking the number of fn scopes
1297         // that we pass through, until we find a lifetime with the
1298         // given name or we run out of scopes.
1299         // search.
1300         let mut late_depth = 0;
1301         let mut scope = self.scope;
1302         let mut outermost_body = None;
1303         let result = loop {
1304             match *scope {
1305                 Scope::Body { id, s } => {
1306                     outermost_body = Some(id);
1307                     scope = s;
1308                 }
1309
1310                 Scope::Root => {
1311                     break None;
1312                 }
1313
1314                 Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
1315                     if let Some(&def) = lifetimes.get(&region_def_id) {
1316                         break Some(def.shifted(late_depth));
1317                     }
1318                     match scope_type {
1319                         BinderScopeType::Normal => late_depth += 1,
1320                         BinderScopeType::Concatenating => {}
1321                     }
1322                     // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
1323                     // regular fns.
1324                     if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1325                         && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
1326                         && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner)
1327                         && !self.tcx.features().anonymous_lifetime_in_impl_trait
1328                     {
1329                         rustc_session::parse::feature_err(
1330                             &self.tcx.sess.parse_sess,
1331                             sym::anonymous_lifetime_in_impl_trait,
1332                             lifetime_ref.span,
1333                             "anonymous lifetimes in `impl Trait` are unstable",
1334                         ).emit();
1335                         return;
1336                     }
1337                     scope = s;
1338                 }
1339
1340                 Scope::Elision { s, .. }
1341                 | Scope::ObjectLifetimeDefault { s, .. }
1342                 | Scope::Supertrait { s, .. }
1343                 | Scope::TraitRefBoundary { s, .. } => {
1344                     scope = s;
1345                 }
1346             }
1347         };
1348
1349         if let Some(mut def) = result {
1350             if let Region::EarlyBound(..) = def {
1351                 // Do not free early-bound regions, only late-bound ones.
1352             } else if let Some(body_id) = outermost_body {
1353                 let fn_id = self.tcx.hir().body_owner(body_id);
1354                 match self.tcx.hir().get(fn_id) {
1355                     Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
1356                     | Node::TraitItem(&hir::TraitItem {
1357                         kind: hir::TraitItemKind::Fn(..), ..
1358                     })
1359                     | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
1360                         let scope = self.tcx.hir().local_def_id(fn_id);
1361                         def = Region::Free(scope.to_def_id(), def.id().unwrap());
1362                     }
1363                     _ => {}
1364                 }
1365             }
1366
1367             self.insert_lifetime(lifetime_ref, def);
1368             return;
1369         }
1370
1371         // We may fail to resolve higher-ranked lifetimes that are mentionned by APIT.
1372         // AST-based resolution does not care for impl-trait desugaring, which are the
1373         // responibility of lowering.  This may create a mismatch between the resolution
1374         // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1375         // ```
1376         // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1377         // ```
1378         //
1379         // In such case, walk back the binders to diagnose it properly.
1380         let mut scope = self.scope;
1381         loop {
1382             match *scope {
1383                 Scope::Binder {
1384                     where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1385                 } => {
1386                     let mut err = self.tcx.sess.struct_span_err(
1387                         lifetime_ref.span,
1388                         "`impl Trait` can only mention lifetimes bound at the fn or impl level",
1389                     );
1390                     err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1391                     err.emit();
1392                     return;
1393                 }
1394                 Scope::Root => break,
1395                 Scope::Binder { s, .. }
1396                 | Scope::Body { s, .. }
1397                 | Scope::Elision { s, .. }
1398                 | Scope::ObjectLifetimeDefault { s, .. }
1399                 | Scope::Supertrait { s, .. }
1400                 | Scope::TraitRefBoundary { s, .. } => {
1401                     scope = s;
1402                 }
1403             }
1404         }
1405
1406         self.tcx.sess.delay_span_bug(
1407             lifetime_ref.span,
1408             &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1409         );
1410     }
1411
1412     fn visit_segment_args(
1413         &mut self,
1414         res: Res,
1415         depth: usize,
1416         generic_args: &'tcx hir::GenericArgs<'tcx>,
1417     ) {
1418         debug!(
1419             "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})",
1420             res, depth, generic_args,
1421         );
1422
1423         if generic_args.parenthesized {
1424             self.visit_fn_like_elision(
1425                 generic_args.inputs(),
1426                 Some(generic_args.bindings[0].ty()),
1427                 false,
1428             );
1429             return;
1430         }
1431
1432         for arg in generic_args.args {
1433             if let hir::GenericArg::Lifetime(lt) = arg {
1434                 self.visit_lifetime(lt);
1435             }
1436         }
1437
1438         // Figure out if this is a type/trait segment,
1439         // which requires object lifetime defaults.
1440         let type_def_id = match res {
1441             Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1442             Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1443             Res::Def(
1444                 DefKind::Struct
1445                 | DefKind::Union
1446                 | DefKind::Enum
1447                 | DefKind::TyAlias
1448                 | DefKind::Trait,
1449                 def_id,
1450             ) if depth == 0 => Some(def_id),
1451             _ => None,
1452         };
1453
1454         debug!("visit_segment_args: type_def_id={:?}", type_def_id);
1455
1456         // Compute a vector of defaults, one for each type parameter,
1457         // per the rules given in RFCs 599 and 1156. Example:
1458         //
1459         // ```rust
1460         // struct Foo<'a, T: 'a, U> { }
1461         // ```
1462         //
1463         // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1464         // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1465         // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1466         // such bound).
1467         //
1468         // Therefore, we would compute `object_lifetime_defaults` to a
1469         // vector like `['x, 'static]`. Note that the vector only
1470         // includes type parameters.
1471         let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1472             let in_body = {
1473                 let mut scope = self.scope;
1474                 loop {
1475                     match *scope {
1476                         Scope::Root => break false,
1477
1478                         Scope::Body { .. } => break true,
1479
1480                         Scope::Binder { s, .. }
1481                         | Scope::Elision { s, .. }
1482                         | Scope::ObjectLifetimeDefault { s, .. }
1483                         | Scope::Supertrait { s, .. }
1484                         | Scope::TraitRefBoundary { s, .. } => {
1485                             scope = s;
1486                         }
1487                     }
1488                 }
1489             };
1490
1491             let map = &self.map;
1492             let generics = self.tcx.generics_of(def_id);
1493             let set_to_region = |set: ObjectLifetimeDefault| match set {
1494                 ObjectLifetimeDefault::Empty => {
1495                     if in_body {
1496                         None
1497                     } else {
1498                         Some(Region::Static)
1499                     }
1500                 }
1501                 ObjectLifetimeDefault::Static => Some(Region::Static),
1502                 ObjectLifetimeDefault::Param(param_def_id) => {
1503                     let index = generics.param_def_id_to_index[&param_def_id];
1504                     generic_args.args.get(index as usize).and_then(|arg| match arg {
1505                         GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
1506                         _ => None,
1507                     })
1508                 }
1509                 ObjectLifetimeDefault::Ambiguous => None,
1510             };
1511             generics
1512                 .params
1513                 .iter()
1514                 .filter_map(|param| self.tcx.object_lifetime_default(param.def_id))
1515                 .map(set_to_region)
1516                 .collect()
1517         });
1518
1519         debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults);
1520
1521         let mut i = 0;
1522         for arg in generic_args.args {
1523             match arg {
1524                 GenericArg::Lifetime(_) => {}
1525                 GenericArg::Type(ty) => {
1526                     if let Some(&lt) = object_lifetime_defaults.get(i) {
1527                         let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1528                         self.with(scope, |this| this.visit_ty(ty));
1529                     } else {
1530                         self.visit_ty(ty);
1531                     }
1532                     i += 1;
1533                 }
1534                 GenericArg::Const(ct) => {
1535                     self.visit_anon_const(&ct.value);
1536                     i += 1;
1537                 }
1538                 GenericArg::Infer(inf) => {
1539                     self.visit_id(inf.hir_id);
1540                     i += 1;
1541                 }
1542             }
1543         }
1544
1545         // Hack: when resolving the type `XX` in binding like `dyn
1546         // Foo<'b, Item = XX>`, the current object-lifetime default
1547         // would be to examine the trait `Foo` to check whether it has
1548         // a lifetime bound declared on `Item`. e.g., if `Foo` is
1549         // declared like so, then the default object lifetime bound in
1550         // `XX` should be `'b`:
1551         //
1552         // ```rust
1553         // trait Foo<'a> {
1554         //   type Item: 'a;
1555         // }
1556         // ```
1557         //
1558         // but if we just have `type Item;`, then it would be
1559         // `'static`. However, we don't get all of this logic correct.
1560         //
1561         // Instead, we do something hacky: if there are no lifetime parameters
1562         // to the trait, then we simply use a default object lifetime
1563         // bound of `'static`, because there is no other possibility. On the other hand,
1564         // if there ARE lifetime parameters, then we require the user to give an
1565         // explicit bound for now.
1566         //
1567         // This is intended to leave room for us to implement the
1568         // correct behavior in the future.
1569         let has_lifetime_parameter =
1570             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1571
1572         // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
1573         // in the trait ref `YY<...>` in `Item: YY<...>`.
1574         for binding in generic_args.bindings {
1575             let scope = Scope::ObjectLifetimeDefault {
1576                 lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
1577                 s: self.scope,
1578             };
1579             if let Some(type_def_id) = type_def_id {
1580                 let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
1581                     self.tcx,
1582                     type_def_id,
1583                     binding.ident,
1584                 );
1585                 self.with(scope, |this| {
1586                     let scope = Scope::Supertrait {
1587                         lifetimes: lifetimes.unwrap_or_default(),
1588                         s: this.scope,
1589                     };
1590                     this.with(scope, |this| this.visit_assoc_type_binding(binding));
1591                 });
1592             } else {
1593                 self.with(scope, |this| this.visit_assoc_type_binding(binding));
1594             }
1595         }
1596     }
1597
1598     /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
1599     /// associated type name and starting trait.
1600     /// For example, imagine we have
1601     /// ```ignore (illustrative)
1602     /// trait Foo<'a, 'b> {
1603     ///   type As;
1604     /// }
1605     /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
1606     /// trait Bar: for<'b> Bar<'b> {}
1607     /// ```
1608     /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
1609     /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
1610     fn supertrait_hrtb_lifetimes(
1611         tcx: TyCtxt<'tcx>,
1612         def_id: DefId,
1613         assoc_name: Ident,
1614     ) -> Option<Vec<ty::BoundVariableKind>> {
1615         let trait_defines_associated_type_named = |trait_def_id: DefId| {
1616             tcx.associated_items(trait_def_id)
1617                 .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
1618                 .is_some()
1619         };
1620
1621         use smallvec::{smallvec, SmallVec};
1622         let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1623             smallvec![(def_id, smallvec![])];
1624         let mut visited: FxHashSet<DefId> = FxHashSet::default();
1625         loop {
1626             let Some((def_id, bound_vars)) = stack.pop() else {
1627                 break None;
1628             };
1629             // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
1630             // there being no supertrait HRTBs.
1631             match tcx.def_kind(def_id) {
1632                 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {}
1633                 _ => break None,
1634             }
1635
1636             if trait_defines_associated_type_named(def_id) {
1637                 break Some(bound_vars.into_iter().collect());
1638             }
1639             let predicates =
1640                 tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
1641             let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
1642                 let bound_predicate = pred.kind();
1643                 match bound_predicate.skip_binder() {
1644                     ty::PredicateKind::Trait(data) => {
1645                         // The order here needs to match what we would get from `subst_supertrait`
1646                         let pred_bound_vars = bound_predicate.bound_vars();
1647                         let mut all_bound_vars = bound_vars.clone();
1648                         all_bound_vars.extend(pred_bound_vars.iter());
1649                         let super_def_id = data.trait_ref.def_id;
1650                         Some((super_def_id, all_bound_vars))
1651                     }
1652                     _ => None,
1653                 }
1654             });
1655
1656             let obligations = obligations.filter(|o| visited.insert(o.0));
1657             stack.extend(obligations);
1658         }
1659     }
1660
1661     #[tracing::instrument(level = "debug", skip(self))]
1662     fn visit_fn_like_elision(
1663         &mut self,
1664         inputs: &'tcx [hir::Ty<'tcx>],
1665         output: Option<&'tcx hir::Ty<'tcx>>,
1666         in_closure: bool,
1667     ) {
1668         self.with(Scope::Elision { s: self.scope }, |this| {
1669             for input in inputs {
1670                 this.visit_ty(input);
1671             }
1672             if !in_closure && let Some(output) = output {
1673                 this.visit_ty(output);
1674             }
1675         });
1676         if in_closure && let Some(output) = output {
1677             self.visit_ty(output);
1678         }
1679     }
1680
1681     fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1682         debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
1683         let mut late_depth = 0;
1684         let mut scope = self.scope;
1685         let lifetime = loop {
1686             match *scope {
1687                 Scope::Binder { s, scope_type, .. } => {
1688                     match scope_type {
1689                         BinderScopeType::Normal => late_depth += 1,
1690                         BinderScopeType::Concatenating => {}
1691                     }
1692                     scope = s;
1693                 }
1694
1695                 Scope::Root | Scope::Elision { .. } => break Region::Static,
1696
1697                 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
1698
1699                 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
1700
1701                 Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
1702                     scope = s;
1703                 }
1704             }
1705         };
1706         self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
1707     }
1708
1709     #[tracing::instrument(level = "debug", skip(self))]
1710     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
1711         debug!(
1712             node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
1713             span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span)
1714         );
1715         self.map.defs.insert(lifetime_ref.hir_id, def);
1716     }
1717
1718     /// Sometimes we resolve a lifetime, but later find that it is an
1719     /// error (esp. around impl trait). In that case, we remove the
1720     /// entry into `map.defs` so as not to confuse later code.
1721     fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
1722         let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
1723         assert_eq!(old_value, Some(bad_def));
1724     }
1725 }
1726
1727 /// Detects late-bound lifetimes and inserts them into
1728 /// `late_bound`.
1729 ///
1730 /// A region declared on a fn is **late-bound** if:
1731 /// - it is constrained by an argument type;
1732 /// - it does not appear in a where-clause.
1733 ///
1734 /// "Constrained" basically means that it appears in any type but
1735 /// not amongst the inputs to a projection. In other words, `<&'a
1736 /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
1737 fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<LocalDefId>> {
1738     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
1739     let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
1740     let generics = tcx.hir().get_generics(def_id)?;
1741
1742     let mut late_bound = FxIndexSet::default();
1743
1744     let mut constrained_by_input = ConstrainedCollector::default();
1745     for arg_ty in decl.inputs {
1746         constrained_by_input.visit_ty(arg_ty);
1747     }
1748
1749     let mut appears_in_output = AllCollector::default();
1750     intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
1751
1752     debug!(?constrained_by_input.regions);
1753
1754     // Walk the lifetimes that appear in where clauses.
1755     //
1756     // Subtle point: because we disallow nested bindings, we can just
1757     // ignore binders here and scrape up all names we see.
1758     let mut appears_in_where_clause = AllCollector::default();
1759     appears_in_where_clause.visit_generics(generics);
1760     debug!(?appears_in_where_clause.regions);
1761
1762     // Late bound regions are those that:
1763     // - appear in the inputs
1764     // - do not appear in the where-clauses
1765     // - are not implicitly captured by `impl Trait`
1766     for param in generics.params {
1767         match param.kind {
1768             hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
1769
1770             // Neither types nor consts are late-bound.
1771             hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
1772         }
1773
1774         let param_def_id = tcx.hir().local_def_id(param.hir_id);
1775
1776         // appears in the where clauses? early-bound.
1777         if appears_in_where_clause.regions.contains(&param_def_id) {
1778             continue;
1779         }
1780
1781         // does not appear in the inputs, but appears in the return type? early-bound.
1782         if !constrained_by_input.regions.contains(&param_def_id)
1783             && appears_in_output.regions.contains(&param_def_id)
1784         {
1785             continue;
1786         }
1787
1788         debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
1789
1790         let inserted = late_bound.insert(param_def_id);
1791         assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
1792     }
1793
1794     debug!(?late_bound);
1795     return Some(tcx.arena.alloc(late_bound));
1796
1797     #[derive(Default)]
1798     struct ConstrainedCollector {
1799         regions: FxHashSet<LocalDefId>,
1800     }
1801
1802     impl<'v> Visitor<'v> for ConstrainedCollector {
1803         fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
1804             match ty.kind {
1805                 hir::TyKind::Path(
1806                     hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
1807                 ) => {
1808                     // ignore lifetimes appearing in associated type
1809                     // projections, as they are not *constrained*
1810                     // (defined above)
1811                 }
1812
1813                 hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
1814                     // consider only the lifetimes on the final
1815                     // segment; I am not sure it's even currently
1816                     // valid to have them elsewhere, but even if it
1817                     // is, those would be potentially inputs to
1818                     // projections
1819                     if let Some(last_segment) = path.segments.last() {
1820                         self.visit_path_segment(path.span, last_segment);
1821                     }
1822                 }
1823
1824                 _ => {
1825                     intravisit::walk_ty(self, ty);
1826                 }
1827             }
1828         }
1829
1830         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
1831             if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
1832                 self.regions.insert(def_id);
1833             }
1834         }
1835     }
1836
1837     #[derive(Default)]
1838     struct AllCollector {
1839         regions: FxHashSet<LocalDefId>,
1840     }
1841
1842     impl<'v> Visitor<'v> for AllCollector {
1843         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
1844             if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
1845                 self.regions.insert(def_id);
1846             }
1847         }
1848     }
1849 }