]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_resolve/src/late/lifetimes.rs
Rollup merge of #101142 - nnethercote:improve-hir-stats, r=davidtwco
[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 #[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 #[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     #[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     #[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>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
1152     debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
1153     let param_def_id = param_def_id.expect_local();
1154     let parent_def_id = tcx.local_parent(param_def_id);
1155     let generics = tcx.hir().get_generics(parent_def_id).unwrap();
1156     let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1157     let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
1158
1159     // Scan the bounds and where-clauses on parameters to extract bounds
1160     // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1161     // for each type parameter.
1162     match param.kind {
1163         GenericParamKind::Type { .. } => {
1164             let mut set = Set1::Empty;
1165
1166             // Look for `type: ...` where clauses.
1167             for bound in generics.bounds_for_param(param_def_id) {
1168                 // Ignore `for<'a> type: ...` as they can change what
1169                 // lifetimes mean (although we could "just" handle it).
1170                 if !bound.bound_generic_params.is_empty() {
1171                     continue;
1172                 }
1173
1174                 for bound in bound.bounds {
1175                     if let hir::GenericBound::Outlives(ref lifetime) = *bound {
1176                         set.insert(lifetime.name.normalize_to_macros_2_0());
1177                     }
1178                 }
1179             }
1180
1181             match set {
1182                 Set1::Empty => ObjectLifetimeDefault::Empty,
1183                 Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
1184                 Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
1185                     ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1186                 }
1187                 _ => ObjectLifetimeDefault::Ambiguous,
1188             }
1189         }
1190         _ => {
1191             bug!("object_lifetime_default_raw must only be called on a type parameter")
1192         }
1193     }
1194 }
1195
1196 impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1197     fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1198     where
1199         F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
1200     {
1201         let LifetimeContext { tcx, map, .. } = self;
1202         let mut this = LifetimeContext {
1203             tcx: *tcx,
1204             map,
1205             scope: &wrap_scope,
1206             trait_definition_only: self.trait_definition_only,
1207         };
1208         let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
1209         {
1210             let _enter = span.enter();
1211             f(&mut this);
1212         }
1213     }
1214
1215     /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1216     ///
1217     /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1218     /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1219     /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1220     ///
1221     /// For example:
1222     ///
1223     ///    fn foo<'a,'b,'c,T:Trait<'b>>(...)
1224     ///
1225     /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1226     /// lifetimes may be interspersed together.
1227     ///
1228     /// If early bound lifetimes are present, we separate them into their own list (and likewise
1229     /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1230     /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1231     /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1232     /// ordering is not important there.
1233     fn visit_early_late<F>(
1234         &mut self,
1235         hir_id: hir::HirId,
1236         generics: &'tcx hir::Generics<'tcx>,
1237         walk: F,
1238     ) where
1239         F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
1240     {
1241         let mut named_late_bound_vars = 0;
1242         let lifetimes: FxIndexMap<LocalDefId, Region> = generics
1243             .params
1244             .iter()
1245             .filter_map(|param| match param.kind {
1246                 GenericParamKind::Lifetime { .. } => {
1247                     if self.tcx.is_late_bound(param.hir_id) {
1248                         let late_bound_idx = named_late_bound_vars;
1249                         named_late_bound_vars += 1;
1250                         Some(Region::late(late_bound_idx, self.tcx.hir(), param))
1251                     } else {
1252                         Some(Region::early(self.tcx.hir(), param))
1253                     }
1254                 }
1255                 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
1256             })
1257             .collect();
1258
1259         let binders: Vec<_> = generics
1260             .params
1261             .iter()
1262             .filter(|param| {
1263                 matches!(param.kind, GenericParamKind::Lifetime { .. })
1264                     && self.tcx.is_late_bound(param.hir_id)
1265             })
1266             .enumerate()
1267             .map(|(late_bound_idx, param)| {
1268                 let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
1269                 late_region_as_bound_region(self.tcx, &pair.1)
1270             })
1271             .collect();
1272         self.map.late_bound_vars.insert(hir_id, binders);
1273         let scope = Scope::Binder {
1274             hir_id,
1275             lifetimes,
1276             s: self.scope,
1277             scope_type: BinderScopeType::Normal,
1278             where_bound_origin: None,
1279         };
1280         self.with(scope, walk);
1281     }
1282
1283     #[instrument(level = "debug", skip(self))]
1284     fn resolve_lifetime_ref(
1285         &mut self,
1286         region_def_id: LocalDefId,
1287         lifetime_ref: &'tcx hir::Lifetime,
1288     ) {
1289         // Walk up the scope chain, tracking the number of fn scopes
1290         // that we pass through, until we find a lifetime with the
1291         // given name or we run out of scopes.
1292         // search.
1293         let mut late_depth = 0;
1294         let mut scope = self.scope;
1295         let mut outermost_body = None;
1296         let result = loop {
1297             match *scope {
1298                 Scope::Body { id, s } => {
1299                     outermost_body = Some(id);
1300                     scope = s;
1301                 }
1302
1303                 Scope::Root => {
1304                     break None;
1305                 }
1306
1307                 Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
1308                     if let Some(&def) = lifetimes.get(&region_def_id) {
1309                         break Some(def.shifted(late_depth));
1310                     }
1311                     match scope_type {
1312                         BinderScopeType::Normal => late_depth += 1,
1313                         BinderScopeType::Concatenating => {}
1314                     }
1315                     // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
1316                     // regular fns.
1317                     if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1318                         && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
1319                         && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner)
1320                         && !self.tcx.features().anonymous_lifetime_in_impl_trait
1321                     {
1322                         rustc_session::parse::feature_err(
1323                             &self.tcx.sess.parse_sess,
1324                             sym::anonymous_lifetime_in_impl_trait,
1325                             lifetime_ref.span,
1326                             "anonymous lifetimes in `impl Trait` are unstable",
1327                         ).emit();
1328                         return;
1329                     }
1330                     scope = s;
1331                 }
1332
1333                 Scope::Elision { s, .. }
1334                 | Scope::ObjectLifetimeDefault { s, .. }
1335                 | Scope::Supertrait { s, .. }
1336                 | Scope::TraitRefBoundary { s, .. } => {
1337                     scope = s;
1338                 }
1339             }
1340         };
1341
1342         if let Some(mut def) = result {
1343             if let Region::EarlyBound(..) = def {
1344                 // Do not free early-bound regions, only late-bound ones.
1345             } else if let Some(body_id) = outermost_body {
1346                 let fn_id = self.tcx.hir().body_owner(body_id);
1347                 match self.tcx.hir().get(fn_id) {
1348                     Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
1349                     | Node::TraitItem(&hir::TraitItem {
1350                         kind: hir::TraitItemKind::Fn(..), ..
1351                     })
1352                     | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
1353                         let scope = self.tcx.hir().local_def_id(fn_id);
1354                         def = Region::Free(scope.to_def_id(), def.id().unwrap());
1355                     }
1356                     _ => {}
1357                 }
1358             }
1359
1360             self.insert_lifetime(lifetime_ref, def);
1361             return;
1362         }
1363
1364         // We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
1365         // AST-based resolution does not care for impl-trait desugaring, which are the
1366         // responibility of lowering.  This may create a mismatch between the resolution
1367         // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1368         // ```
1369         // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1370         // ```
1371         //
1372         // In such case, walk back the binders to diagnose it properly.
1373         let mut scope = self.scope;
1374         loop {
1375             match *scope {
1376                 Scope::Binder {
1377                     where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1378                 } => {
1379                     let mut err = self.tcx.sess.struct_span_err(
1380                         lifetime_ref.span,
1381                         "`impl Trait` can only mention lifetimes bound at the fn or impl level",
1382                     );
1383                     err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1384                     err.emit();
1385                     return;
1386                 }
1387                 Scope::Root => break,
1388                 Scope::Binder { s, .. }
1389                 | Scope::Body { s, .. }
1390                 | Scope::Elision { s, .. }
1391                 | Scope::ObjectLifetimeDefault { s, .. }
1392                 | Scope::Supertrait { s, .. }
1393                 | Scope::TraitRefBoundary { s, .. } => {
1394                     scope = s;
1395                 }
1396             }
1397         }
1398
1399         self.tcx.sess.delay_span_bug(
1400             lifetime_ref.span,
1401             &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1402         );
1403     }
1404
1405     #[instrument(level = "debug", skip(self))]
1406     fn visit_segment_args(
1407         &mut self,
1408         res: Res,
1409         depth: usize,
1410         generic_args: &'tcx hir::GenericArgs<'tcx>,
1411     ) {
1412         if generic_args.parenthesized {
1413             self.visit_fn_like_elision(
1414                 generic_args.inputs(),
1415                 Some(generic_args.bindings[0].ty()),
1416                 false,
1417             );
1418             return;
1419         }
1420
1421         for arg in generic_args.args {
1422             if let hir::GenericArg::Lifetime(lt) = arg {
1423                 self.visit_lifetime(lt);
1424             }
1425         }
1426
1427         // Figure out if this is a type/trait segment,
1428         // which requires object lifetime defaults.
1429         let type_def_id = match res {
1430             Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1431             Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1432             Res::Def(
1433                 DefKind::Struct
1434                 | DefKind::Union
1435                 | DefKind::Enum
1436                 | DefKind::TyAlias
1437                 | DefKind::Trait,
1438                 def_id,
1439             ) if depth == 0 => Some(def_id),
1440             _ => None,
1441         };
1442
1443         debug!(?type_def_id);
1444
1445         // Compute a vector of defaults, one for each type parameter,
1446         // per the rules given in RFCs 599 and 1156. Example:
1447         //
1448         // ```rust
1449         // struct Foo<'a, T: 'a, U> { }
1450         // ```
1451         //
1452         // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1453         // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1454         // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1455         // such bound).
1456         //
1457         // Therefore, we would compute `object_lifetime_defaults` to a
1458         // vector like `['x, 'static]`. Note that the vector only
1459         // includes type parameters.
1460         let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1461             let in_body = {
1462                 let mut scope = self.scope;
1463                 loop {
1464                     match *scope {
1465                         Scope::Root => break false,
1466
1467                         Scope::Body { .. } => break true,
1468
1469                         Scope::Binder { s, .. }
1470                         | Scope::Elision { s, .. }
1471                         | Scope::ObjectLifetimeDefault { s, .. }
1472                         | Scope::Supertrait { s, .. }
1473                         | Scope::TraitRefBoundary { s, .. } => {
1474                             scope = s;
1475                         }
1476                     }
1477                 }
1478             };
1479
1480             let map = &self.map;
1481             let generics = self.tcx.generics_of(def_id);
1482
1483             // `type_def_id` points to an item, so there is nothing to inherit generics from.
1484             debug_assert_eq!(generics.parent_count, 0);
1485
1486             let set_to_region = |set: ObjectLifetimeDefault| match set {
1487                 ObjectLifetimeDefault::Empty => {
1488                     if in_body {
1489                         None
1490                     } else {
1491                         Some(Region::Static)
1492                     }
1493                 }
1494                 ObjectLifetimeDefault::Static => Some(Region::Static),
1495                 ObjectLifetimeDefault::Param(param_def_id) => {
1496                     // This index can be used with `generic_args` since `parent_count == 0`.
1497                     let index = generics.param_def_id_to_index[&param_def_id] as usize;
1498                     generic_args.args.get(index).and_then(|arg| match arg {
1499                         GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
1500                         _ => None,
1501                     })
1502                 }
1503                 ObjectLifetimeDefault::Ambiguous => None,
1504             };
1505             generics
1506                 .params
1507                 .iter()
1508                 .filter_map(|param| {
1509                     match self.tcx.def_kind(param.def_id) {
1510                         // Generic consts don't impose any constraints.
1511                         //
1512                         // We still store a dummy value here to allow generic parameters
1513                         // in an arbitrary order.
1514                         DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
1515                         DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
1516                         // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
1517                         // works.  Ignore it because it can't have a meaningful lifetime default.
1518                         DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
1519                         dk => bug!("unexpected def_kind {:?}", dk),
1520                     }
1521                 })
1522                 .map(set_to_region)
1523                 .collect()
1524         });
1525
1526         debug!(?object_lifetime_defaults);
1527
1528         let mut i = 0;
1529         for arg in generic_args.args {
1530             match arg {
1531                 GenericArg::Lifetime(_) => {}
1532                 GenericArg::Type(ty) => {
1533                     if let Some(&lt) = object_lifetime_defaults.get(i) {
1534                         let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1535                         self.with(scope, |this| this.visit_ty(ty));
1536                     } else {
1537                         self.visit_ty(ty);
1538                     }
1539                     i += 1;
1540                 }
1541                 GenericArg::Const(ct) => {
1542                     self.visit_anon_const(&ct.value);
1543                     i += 1;
1544                 }
1545                 GenericArg::Infer(inf) => {
1546                     self.visit_id(inf.hir_id);
1547                     i += 1;
1548                 }
1549             }
1550         }
1551
1552         // Hack: when resolving the type `XX` in binding like `dyn
1553         // Foo<'b, Item = XX>`, the current object-lifetime default
1554         // would be to examine the trait `Foo` to check whether it has
1555         // a lifetime bound declared on `Item`. e.g., if `Foo` is
1556         // declared like so, then the default object lifetime bound in
1557         // `XX` should be `'b`:
1558         //
1559         // ```rust
1560         // trait Foo<'a> {
1561         //   type Item: 'a;
1562         // }
1563         // ```
1564         //
1565         // but if we just have `type Item;`, then it would be
1566         // `'static`. However, we don't get all of this logic correct.
1567         //
1568         // Instead, we do something hacky: if there are no lifetime parameters
1569         // to the trait, then we simply use a default object lifetime
1570         // bound of `'static`, because there is no other possibility. On the other hand,
1571         // if there ARE lifetime parameters, then we require the user to give an
1572         // explicit bound for now.
1573         //
1574         // This is intended to leave room for us to implement the
1575         // correct behavior in the future.
1576         let has_lifetime_parameter =
1577             generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1578
1579         // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
1580         // in the trait ref `YY<...>` in `Item: YY<...>`.
1581         for binding in generic_args.bindings {
1582             let scope = Scope::ObjectLifetimeDefault {
1583                 lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
1584                 s: self.scope,
1585             };
1586             if let Some(type_def_id) = type_def_id {
1587                 let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
1588                     self.tcx,
1589                     type_def_id,
1590                     binding.ident,
1591                 );
1592                 self.with(scope, |this| {
1593                     let scope = Scope::Supertrait {
1594                         lifetimes: lifetimes.unwrap_or_default(),
1595                         s: this.scope,
1596                     };
1597                     this.with(scope, |this| this.visit_assoc_type_binding(binding));
1598                 });
1599             } else {
1600                 self.with(scope, |this| this.visit_assoc_type_binding(binding));
1601             }
1602         }
1603     }
1604
1605     /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
1606     /// associated type name and starting trait.
1607     /// For example, imagine we have
1608     /// ```ignore (illustrative)
1609     /// trait Foo<'a, 'b> {
1610     ///   type As;
1611     /// }
1612     /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
1613     /// trait Bar: for<'b> Bar<'b> {}
1614     /// ```
1615     /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
1616     /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
1617     fn supertrait_hrtb_lifetimes(
1618         tcx: TyCtxt<'tcx>,
1619         def_id: DefId,
1620         assoc_name: Ident,
1621     ) -> Option<Vec<ty::BoundVariableKind>> {
1622         let trait_defines_associated_type_named = |trait_def_id: DefId| {
1623             tcx.associated_items(trait_def_id)
1624                 .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
1625                 .is_some()
1626         };
1627
1628         use smallvec::{smallvec, SmallVec};
1629         let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1630             smallvec![(def_id, smallvec![])];
1631         let mut visited: FxHashSet<DefId> = FxHashSet::default();
1632         loop {
1633             let Some((def_id, bound_vars)) = stack.pop() else {
1634                 break None;
1635             };
1636             // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
1637             // there being no supertrait HRTBs.
1638             match tcx.def_kind(def_id) {
1639                 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {}
1640                 _ => break None,
1641             }
1642
1643             if trait_defines_associated_type_named(def_id) {
1644                 break Some(bound_vars.into_iter().collect());
1645             }
1646             let predicates =
1647                 tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
1648             let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
1649                 let bound_predicate = pred.kind();
1650                 match bound_predicate.skip_binder() {
1651                     ty::PredicateKind::Trait(data) => {
1652                         // The order here needs to match what we would get from `subst_supertrait`
1653                         let pred_bound_vars = bound_predicate.bound_vars();
1654                         let mut all_bound_vars = bound_vars.clone();
1655                         all_bound_vars.extend(pred_bound_vars.iter());
1656                         let super_def_id = data.trait_ref.def_id;
1657                         Some((super_def_id, all_bound_vars))
1658                     }
1659                     _ => None,
1660                 }
1661             });
1662
1663             let obligations = obligations.filter(|o| visited.insert(o.0));
1664             stack.extend(obligations);
1665         }
1666     }
1667
1668     #[instrument(level = "debug", skip(self))]
1669     fn visit_fn_like_elision(
1670         &mut self,
1671         inputs: &'tcx [hir::Ty<'tcx>],
1672         output: Option<&'tcx hir::Ty<'tcx>>,
1673         in_closure: bool,
1674     ) {
1675         self.with(Scope::Elision { s: self.scope }, |this| {
1676             for input in inputs {
1677                 this.visit_ty(input);
1678             }
1679             if !in_closure && let Some(output) = output {
1680                 this.visit_ty(output);
1681             }
1682         });
1683         if in_closure && let Some(output) = output {
1684             self.visit_ty(output);
1685         }
1686     }
1687
1688     fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1689         debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
1690         let mut late_depth = 0;
1691         let mut scope = self.scope;
1692         let lifetime = loop {
1693             match *scope {
1694                 Scope::Binder { s, scope_type, .. } => {
1695                     match scope_type {
1696                         BinderScopeType::Normal => late_depth += 1,
1697                         BinderScopeType::Concatenating => {}
1698                     }
1699                     scope = s;
1700                 }
1701
1702                 Scope::Root | Scope::Elision { .. } => break Region::Static,
1703
1704                 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
1705
1706                 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
1707
1708                 Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
1709                     scope = s;
1710                 }
1711             }
1712         };
1713         self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
1714     }
1715
1716     #[instrument(level = "debug", skip(self))]
1717     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
1718         debug!(
1719             node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
1720             span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span)
1721         );
1722         self.map.defs.insert(lifetime_ref.hir_id, def);
1723     }
1724
1725     /// Sometimes we resolve a lifetime, but later find that it is an
1726     /// error (esp. around impl trait). In that case, we remove the
1727     /// entry into `map.defs` so as not to confuse later code.
1728     fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
1729         let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
1730         assert_eq!(old_value, Some(bad_def));
1731     }
1732 }
1733
1734 /// Detects late-bound lifetimes and inserts them into
1735 /// `late_bound`.
1736 ///
1737 /// A region declared on a fn is **late-bound** if:
1738 /// - it is constrained by an argument type;
1739 /// - it does not appear in a where-clause.
1740 ///
1741 /// "Constrained" basically means that it appears in any type but
1742 /// not amongst the inputs to a projection. In other words, `<&'a
1743 /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
1744 fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<LocalDefId>> {
1745     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
1746     let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
1747     let generics = tcx.hir().get_generics(def_id)?;
1748
1749     let mut late_bound = FxIndexSet::default();
1750
1751     let mut constrained_by_input = ConstrainedCollector::default();
1752     for arg_ty in decl.inputs {
1753         constrained_by_input.visit_ty(arg_ty);
1754     }
1755
1756     let mut appears_in_output = AllCollector::default();
1757     intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
1758
1759     debug!(?constrained_by_input.regions);
1760
1761     // Walk the lifetimes that appear in where clauses.
1762     //
1763     // Subtle point: because we disallow nested bindings, we can just
1764     // ignore binders here and scrape up all names we see.
1765     let mut appears_in_where_clause = AllCollector::default();
1766     appears_in_where_clause.visit_generics(generics);
1767     debug!(?appears_in_where_clause.regions);
1768
1769     // Late bound regions are those that:
1770     // - appear in the inputs
1771     // - do not appear in the where-clauses
1772     // - are not implicitly captured by `impl Trait`
1773     for param in generics.params {
1774         match param.kind {
1775             hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
1776
1777             // Neither types nor consts are late-bound.
1778             hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
1779         }
1780
1781         let param_def_id = tcx.hir().local_def_id(param.hir_id);
1782
1783         // appears in the where clauses? early-bound.
1784         if appears_in_where_clause.regions.contains(&param_def_id) {
1785             continue;
1786         }
1787
1788         // does not appear in the inputs, but appears in the return type? early-bound.
1789         if !constrained_by_input.regions.contains(&param_def_id)
1790             && appears_in_output.regions.contains(&param_def_id)
1791         {
1792             continue;
1793         }
1794
1795         debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
1796
1797         let inserted = late_bound.insert(param_def_id);
1798         assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
1799     }
1800
1801     debug!(?late_bound);
1802     return Some(tcx.arena.alloc(late_bound));
1803
1804     #[derive(Default)]
1805     struct ConstrainedCollector {
1806         regions: FxHashSet<LocalDefId>,
1807     }
1808
1809     impl<'v> Visitor<'v> for ConstrainedCollector {
1810         fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
1811             match ty.kind {
1812                 hir::TyKind::Path(
1813                     hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
1814                 ) => {
1815                     // ignore lifetimes appearing in associated type
1816                     // projections, as they are not *constrained*
1817                     // (defined above)
1818                 }
1819
1820                 hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
1821                     // consider only the lifetimes on the final
1822                     // segment; I am not sure it's even currently
1823                     // valid to have them elsewhere, but even if it
1824                     // is, those would be potentially inputs to
1825                     // projections
1826                     if let Some(last_segment) = path.segments.last() {
1827                         self.visit_path_segment(path.span, last_segment);
1828                     }
1829                 }
1830
1831                 _ => {
1832                     intravisit::walk_ty(self, ty);
1833                 }
1834             }
1835         }
1836
1837         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
1838             if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
1839                 self.regions.insert(def_id);
1840             }
1841         }
1842     }
1843
1844     #[derive(Default)]
1845     struct AllCollector {
1846         regions: FxHashSet<LocalDefId>,
1847     }
1848
1849     impl<'v> Visitor<'v> for AllCollector {
1850         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
1851             if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
1852                 self.regions.insert(def_id);
1853             }
1854         }
1855     }
1856 }