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