]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_resolve/src/late/lifetimes.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / compiler / rustc_resolve / src / late / lifetimes.rs
1 // ignore-tidy-filelength
2 //! Name resolution for lifetimes.
3 //!
4 //! Name resolution for lifetimes follows *much* simpler rules than the
5 //! full resolve. For example, lifetime names are never exported or
6 //! used between functions, and they operate in a purely top-down
7 //! way. Therefore, we break lifetime name resolution into a separate pass.
8
9 use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
10 use rustc_ast::walk_list;
11 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
12 use rustc_errors::struct_span_err;
13 use rustc_hir as hir;
14 use rustc_hir::def::{DefKind, Res};
15 use rustc_hir::def_id::{DefIdMap, LocalDefId};
16 use rustc_hir::intravisit::{self, Visitor};
17 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
18 use rustc_hir::{GenericParamKind, HirIdMap};
19 use rustc_middle::hir::map::Map;
20 use rustc_middle::hir::nested_filter;
21 use rustc_middle::middle::resolve_lifetime::*;
22 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
23 use rustc_middle::{bug, span_bug};
24 use rustc_span::def_id::DefId;
25 use rustc_span::symbol::{kw, sym, Ident};
26 use rustc_span::Span;
27 use std::borrow::Cow;
28 use std::cell::Cell;
29 use std::fmt;
30 use std::mem::take;
31
32 trait RegionExt {
33 fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
34
35 fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
36
37 fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region;
38
39 fn id(&self) -> Option<DefId>;
40
41 fn shifted(self, amount: u32) -> Region;
42
43 fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
44
45 fn subst<'a, L>(self, params: L, map: &NamedRegionMap) -> Option<Region>
46 where
47 L: Iterator<Item = &'a hir::Lifetime>;
48 }
49
50 impl RegionExt for Region {
51 fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
52 let i = *index;
53 *index += 1;
54 let def_id = hir_map.local_def_id(param.hir_id);
55 debug!("Region::early: index={} def_id={:?}", i, def_id);
56 (def_id, Region::EarlyBound(i, def_id.to_def_id()))
57 }
58
59 fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
60 let depth = ty::INNERMOST;
61 let def_id = hir_map.local_def_id(param.hir_id);
62 debug!(
63 "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
64 idx, param, depth, def_id,
65 );
66 (def_id, Region::LateBound(depth, idx, def_id.to_def_id()))
67 }
68
69 fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region {
70 let i = index.get();
71 index.set(i + 1);
72 let depth = ty::INNERMOST;
73 Region::LateBoundAnon(depth, named_late_bound_vars + i, i)
74 }
75
76 fn id(&self) -> Option<DefId> {
77 match *self {
78 Region::Static | Region::LateBoundAnon(..) => None,
79
80 Region::EarlyBound(_, id) | Region::LateBound(_, _, id) | Region::Free(_, id) => {
81 Some(id)
82 }
83 }
84 }
85
86 fn shifted(self, amount: u32) -> Region {
87 match self {
88 Region::LateBound(debruijn, idx, id) => {
89 Region::LateBound(debruijn.shifted_in(amount), idx, id)
90 }
91 Region::LateBoundAnon(debruijn, index, anon_index) => {
92 Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index)
93 }
94 _ => self,
95 }
96 }
97
98 fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region {
99 match self {
100 Region::LateBound(debruijn, index, id) => {
101 Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id)
102 }
103 Region::LateBoundAnon(debruijn, index, anon_index) => {
104 Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index)
105 }
106 _ => self,
107 }
108 }
109
110 fn subst<'a, L>(self, mut params: L, map: &NamedRegionMap) -> Option<Region>
111 where
112 L: Iterator<Item = &'a hir::Lifetime>,
113 {
114 if let Region::EarlyBound(index, _) = self {
115 params.nth(index as usize).and_then(|lifetime| map.defs.get(&lifetime.hir_id).cloned())
116 } else {
117 Some(self)
118 }
119 }
120 }
121
122 /// Maps the id of each lifetime reference to the lifetime decl
123 /// that it corresponds to.
124 ///
125 /// FIXME. This struct gets converted to a `ResolveLifetimes` for
126 /// actual use. It has the same data, but indexed by `LocalDefId`. This
127 /// is silly.
128 #[derive(Debug, Default)]
129 struct NamedRegionMap {
130 // maps from every use of a named (not anonymous) lifetime to a
131 // `Region` describing how that region is bound
132 defs: HirIdMap<Region>,
133
134 // Maps relevant hir items to the bound vars on them. These include:
135 // - function defs
136 // - function pointers
137 // - closures
138 // - trait refs
139 // - bound types (like `T` in `for<'a> T<'a>: Foo`)
140 late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
141 }
142
143 pub(crate) struct LifetimeContext<'a, 'tcx> {
144 pub(crate) tcx: TyCtxt<'tcx>,
145 map: &'a mut NamedRegionMap,
146 scope: ScopeRef<'a>,
147
148 /// Indicates that we only care about the definition of a trait. This should
149 /// be false if the `Item` we are resolving lifetimes for is not a trait or
150 /// we eventually need lifetimes resolve for trait items.
151 trait_definition_only: bool,
152
153 /// Cache for cross-crate per-definition object lifetime defaults.
154 xcrate_object_lifetime_defaults: DefIdMap<Vec<ObjectLifetimeDefault>>,
155
156 /// When encountering an undefined named lifetime, we will suggest introducing it in these
157 /// places.
158 pub(crate) missing_named_lifetime_spots: Vec<MissingLifetimeSpot<'tcx>>,
159 }
160
161 #[derive(Debug)]
162 enum Scope<'a> {
163 /// Declares lifetimes, and each can be early-bound or late-bound.
164 /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
165 /// it should be shifted by the number of `Binder`s in between the
166 /// declaration `Binder` and the location it's referenced from.
167 Binder {
168 /// We use an IndexMap here because we want these lifetimes in order
169 /// for diagnostics.
170 lifetimes: FxIndexMap<LocalDefId, Region>,
171
172 /// if we extend this scope with another scope, what is the next index
173 /// we should use for an early-bound region?
174 next_early_index: u32,
175
176 /// Whether or not this binder would serve as the parent
177 /// binder for opaque types introduced within. For example:
178 ///
179 /// ```text
180 /// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
181 /// ```
182 ///
183 /// Here, the opaque types we create for the `impl Trait`
184 /// and `impl Trait2` references will both have the `foo` item
185 /// as their parent. When we get to `impl Trait2`, we find
186 /// that it is nested within the `for<>` binder -- this flag
187 /// allows us to skip that when looking for the parent binder
188 /// of the resulting opaque type.
189 opaque_type_parent: bool,
190
191 scope_type: BinderScopeType,
192
193 /// The late bound vars for a given item are stored by `HirId` to be
194 /// queried later. However, if we enter an elision scope, we have to
195 /// later append the elided bound vars to the list and need to know what
196 /// to append to.
197 hir_id: hir::HirId,
198
199 s: ScopeRef<'a>,
200
201 /// In some cases not allowing late bounds allows us to avoid ICEs.
202 /// This is almost ways set to true.
203 allow_late_bound: bool,
204
205 /// If this binder comes from a where clause, specify how it was created.
206 /// This is used to diagnose inaccessible lifetimes in APIT:
207 /// ```ignore (illustrative)
208 /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
209 /// ```
210 where_bound_origin: Option<hir::PredicateOrigin>,
211 },
212
213 /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
214 /// if this is a fn body, otherwise the original definitions are used.
215 /// Unspecified lifetimes are inferred, unless an elision scope is nested,
216 /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
217 Body {
218 id: hir::BodyId,
219 s: ScopeRef<'a>,
220 },
221
222 /// A scope which either determines unspecified lifetimes or errors
223 /// on them (e.g., due to ambiguity). For more details, see `Elide`.
224 Elision {
225 elide: Elide,
226 s: ScopeRef<'a>,
227 },
228
229 /// Use a specific lifetime (if `Some`) or leave it unset (to be
230 /// inferred in a function body or potentially error outside one),
231 /// for the default choice of lifetime in a trait object type.
232 ObjectLifetimeDefault {
233 lifetime: Option<Region>,
234 s: ScopeRef<'a>,
235 },
236
237 /// When we have nested trait refs, we concatenate late bound vars for inner
238 /// trait refs from outer ones. But we also need to include any HRTB
239 /// lifetimes encountered when identifying the trait that an associated type
240 /// is declared on.
241 Supertrait {
242 lifetimes: Vec<ty::BoundVariableKind>,
243 s: ScopeRef<'a>,
244 },
245
246 TraitRefBoundary {
247 s: ScopeRef<'a>,
248 },
249
250 Root,
251 }
252
253 #[derive(Copy, Clone, Debug)]
254 enum BinderScopeType {
255 /// Any non-concatenating binder scopes.
256 Normal,
257 /// Within a syntactic trait ref, there may be multiple poly trait refs that
258 /// are nested (under the `associated_type_bounds` feature). The binders of
259 /// the inner poly trait refs are extended from the outer poly trait refs
260 /// and don't increase the late bound depth. If you had
261 /// `T: for<'a> Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope
262 /// would be `Concatenating`. This also used in trait refs in where clauses
263 /// where we have two binders `for<> T: for<> Foo` (I've intentionally left
264 /// out any lifetimes because they aren't needed to show the two scopes).
265 /// The inner `for<>` has a scope of `Concatenating`.
266 Concatenating,
267 }
268
269 // A helper struct for debugging scopes without printing parent scopes
270 struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
271
272 impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 match self.0 {
275 Scope::Binder {
276 lifetimes,
277 next_early_index,
278 opaque_type_parent,
279 scope_type,
280 hir_id,
281 allow_late_bound,
282 where_bound_origin,
283 s: _,
284 } => f
285 .debug_struct("Binder")
286 .field("lifetimes", lifetimes)
287 .field("next_early_index", next_early_index)
288 .field("opaque_type_parent", opaque_type_parent)
289 .field("scope_type", scope_type)
290 .field("hir_id", hir_id)
291 .field("allow_late_bound", allow_late_bound)
292 .field("where_bound_origin", where_bound_origin)
293 .field("s", &"..")
294 .finish(),
295 Scope::Body { id, s: _ } => {
296 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
297 }
298 Scope::Elision { elide, s: _ } => {
299 f.debug_struct("Elision").field("elide", elide).field("s", &"..").finish()
300 }
301 Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
302 .debug_struct("ObjectLifetimeDefault")
303 .field("lifetime", lifetime)
304 .field("s", &"..")
305 .finish(),
306 Scope::Supertrait { lifetimes, s: _ } => f
307 .debug_struct("Supertrait")
308 .field("lifetimes", lifetimes)
309 .field("s", &"..")
310 .finish(),
311 Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
312 Scope::Root => f.debug_struct("Root").finish(),
313 }
314 }
315 }
316
317 #[derive(Clone, Debug)]
318 enum Elide {
319 /// Use a fresh anonymous late-bound lifetime each time, by
320 /// incrementing the counter to generate sequential indices. All
321 /// anonymous lifetimes must start *after* named bound vars.
322 FreshLateAnon(u32, Cell<u32>),
323 /// Always use this one lifetime.
324 Exact(Region),
325 /// Less or more than one lifetime were found, error on unspecified.
326 Error(Vec<ElisionFailureInfo>),
327 /// Forbid lifetime elision inside of a larger scope where it would be
328 /// permitted. For example, in let position impl trait.
329 Forbid,
330 }
331
332 #[derive(Clone, Debug)]
333 pub(crate) struct ElisionFailureInfo {
334 /// Where we can find the argument pattern.
335 pub(crate) parent: Option<hir::BodyId>,
336 /// The index of the argument in the original definition.
337 pub(crate) index: usize,
338 pub(crate) lifetime_count: usize,
339 pub(crate) have_bound_regions: bool,
340 pub(crate) span: Span,
341 }
342
343 type ScopeRef<'a> = &'a Scope<'a>;
344
345 const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
346
347 pub fn provide(providers: &mut ty::query::Providers) {
348 *providers = ty::query::Providers {
349 resolve_lifetimes_trait_definition,
350 resolve_lifetimes,
351
352 named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
353 is_late_bound_map,
354 object_lifetime_defaults: |tcx, id| match tcx.hir().find_by_def_id(id) {
355 Some(Node::Item(item)) => compute_object_lifetime_defaults(tcx, item),
356 _ => None,
357 },
358 late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
359
360 ..*providers
361 };
362 }
363
364 /// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
365 /// Also does not generate any diagnostics.
366 ///
367 /// This is ultimately a subset of the `resolve_lifetimes` work. It effectively
368 /// resolves lifetimes only within the trait "header" -- that is, the trait
369 /// and supertrait list. In contrast, `resolve_lifetimes` resolves all the
370 /// lifetimes within the trait and its items. There is room to refactor this,
371 /// for example to resolve lifetimes for each trait item in separate queries,
372 /// but it's convenient to do the entire trait at once because the lifetimes
373 /// from the trait definition are in scope within the trait items as well.
374 ///
375 /// The reason for this separate call is to resolve what would otherwise
376 /// be a cycle. Consider this example:
377 ///
378 /// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub)
379 /// trait Base<'a> {
380 /// type BaseItem;
381 /// }
382 /// trait Sub<'b>: for<'a> Base<'a> {
383 /// type SubItem: Sub<BaseItem = &'b u32>;
384 /// }
385 /// ```
386 ///
387 /// When we resolve `Sub` and all its items, we also have to resolve `Sub<BaseItem = &'b u32>`.
388 /// To figure out the index of `'b`, we have to know about the supertraits
389 /// of `Sub` so that we can determine that the `for<'a>` will be in scope.
390 /// (This is because we -- currently at least -- flatten all the late-bound
391 /// lifetimes into a single binder.) This requires us to resolve the
392 /// *trait definition* of `Sub`; basically just enough lifetime information
393 /// to look at the supertraits.
394 #[tracing::instrument(level = "debug", skip(tcx))]
395 fn resolve_lifetimes_trait_definition(
396 tcx: TyCtxt<'_>,
397 local_def_id: LocalDefId,
398 ) -> ResolveLifetimes {
399 convert_named_region_map(do_resolve(tcx, local_def_id, true))
400 }
401
402 /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
403 /// You should not read the result of this query directly, but rather use
404 /// `named_region_map`, `is_late_bound_map`, etc.
405 #[tracing::instrument(level = "debug", skip(tcx))]
406 fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
407 convert_named_region_map(do_resolve(tcx, local_def_id, false))
408 }
409
410 fn do_resolve(
411 tcx: TyCtxt<'_>,
412 local_def_id: LocalDefId,
413 trait_definition_only: bool,
414 ) -> NamedRegionMap {
415 let item = tcx.hir().expect_item(local_def_id);
416 let mut named_region_map =
417 NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
418 let mut visitor = LifetimeContext {
419 tcx,
420 map: &mut named_region_map,
421 scope: ROOT_SCOPE,
422 trait_definition_only,
423 xcrate_object_lifetime_defaults: Default::default(),
424 missing_named_lifetime_spots: vec![],
425 };
426 visitor.visit_item(item);
427
428 named_region_map
429 }
430
431 fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
432 let mut rl = ResolveLifetimes::default();
433
434 for (hir_id, v) in named_region_map.defs {
435 let map = rl.defs.entry(hir_id.owner).or_default();
436 map.insert(hir_id.local_id, v);
437 }
438 for (hir_id, v) in named_region_map.late_bound_vars {
439 let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
440 map.insert(hir_id.local_id, v);
441 }
442
443 debug!(?rl.defs);
444 rl
445 }
446
447 /// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
448 /// There are two important things this does.
449 /// First, we have to resolve lifetimes for
450 /// the entire *`Item`* that contains this owner, because that's the largest "scope"
451 /// where we can have relevant lifetimes.
452 /// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
453 /// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
454 /// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
455 /// other than the trait itself (like the trait methods or associated types), then we just use the regular
456 /// `resolve_lifetimes`.
457 fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes {
458 let item_id = item_for(tcx, def_id);
459 if item_id == def_id {
460 let item = tcx.hir().item(hir::ItemId { def_id: item_id });
461 match item.kind {
462 hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id),
463 _ => tcx.resolve_lifetimes(item_id),
464 }
465 } else {
466 tcx.resolve_lifetimes(item_id)
467 }
468 }
469
470 /// Finds the `Item` that contains the given `LocalDefId`
471 fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
472 match tcx.hir().find_by_def_id(local_def_id) {
473 Some(Node::Item(item)) => {
474 return item.def_id;
475 }
476 _ => {}
477 }
478 let item = {
479 let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
480 let mut parent_iter = tcx.hir().parent_iter(hir_id);
481 loop {
482 let node = parent_iter.next().map(|n| n.1);
483 match node {
484 Some(hir::Node::Item(item)) => break item.def_id,
485 Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."),
486 _ => {}
487 }
488 }
489 };
490 item
491 }
492
493 /// In traits, there is an implicit `Self` type parameter which comes before the generics.
494 /// We have to account for this when computing the index of the other generic parameters.
495 /// This function returns whether there is such an implicit parameter defined on the given item.
496 fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool {
497 matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..))
498 }
499
500 fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
501 match region {
502 Region::LateBound(_, _, def_id) => {
503 let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
504 ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
505 }
506 Region::LateBoundAnon(_, _, anon_idx) => {
507 ty::BoundVariableKind::Region(ty::BrAnon(*anon_idx))
508 }
509 _ => bug!("{:?} is not a late region", region),
510 }
511 }
512
513 impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
514 /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
515 fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
516 let mut scope = self.scope;
517 let mut supertrait_lifetimes = vec![];
518 loop {
519 match scope {
520 Scope::Body { .. } | Scope::Root => {
521 break (vec![], BinderScopeType::Normal);
522 }
523
524 Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
525 scope = s;
526 }
527
528 Scope::Supertrait { s, lifetimes } => {
529 supertrait_lifetimes = lifetimes.clone();
530 scope = s;
531 }
532
533 Scope::TraitRefBoundary { .. } => {
534 // We should only see super trait lifetimes if there is a `Binder` above
535 assert!(supertrait_lifetimes.is_empty());
536 break (vec![], BinderScopeType::Normal);
537 }
538
539 Scope::Binder { hir_id, .. } => {
540 // Nested poly trait refs have the binders concatenated
541 let mut full_binders =
542 self.map.late_bound_vars.entry(*hir_id).or_default().clone();
543 full_binders.extend(supertrait_lifetimes.into_iter());
544 break (full_binders, BinderScopeType::Concatenating);
545 }
546 }
547 }
548 }
549 }
550 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
551 type NestedFilter = nested_filter::All;
552
553 fn nested_visit_map(&mut self) -> Self::Map {
554 self.tcx.hir()
555 }
556
557 // We want to nest trait/impl items in their parent, but nothing else.
558 fn visit_nested_item(&mut self, _: hir::ItemId) {}
559
560 fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) {
561 if !self.trait_definition_only {
562 intravisit::walk_trait_item_ref(self, ii)
563 }
564 }
565
566 fn visit_nested_body(&mut self, body: hir::BodyId) {
567 let body = self.tcx.hir().body(body);
568 self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
569 this.visit_body(body);
570 });
571 }
572
573 fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
574 if let hir::ExprKind::Closure { bound_generic_params, .. } = e.kind {
575 let next_early_index = self.next_early_index();
576 let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
577 bound_generic_params
578 .iter()
579 .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
580 .enumerate()
581 .map(|(late_bound_idx, param)| {
582 let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
583 let r = late_region_as_bound_region(self.tcx, &pair.1);
584 (pair, r)
585 })
586 .unzip();
587 self.map.late_bound_vars.insert(e.hir_id, binders);
588 let scope = Scope::Binder {
589 hir_id: e.hir_id,
590 lifetimes,
591 s: self.scope,
592 next_early_index,
593 opaque_type_parent: false,
594 scope_type: BinderScopeType::Normal,
595 allow_late_bound: true,
596 where_bound_origin: None,
597 };
598 self.with(scope, |this| {
599 // a closure has no bounds, so everything
600 // contained within is scoped within its binder.
601 intravisit::walk_expr(this, e)
602 });
603 } else {
604 intravisit::walk_expr(self, e)
605 }
606 }
607
608 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
609 match &item.kind {
610 hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
611 if let Some(of_trait) = of_trait {
612 self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default());
613 }
614 }
615 _ => {}
616 }
617 match item.kind {
618 hir::ItemKind::Fn(_, ref generics, _) => {
619 self.missing_named_lifetime_spots.push(generics.into());
620 self.visit_early_late(None, item.hir_id(), generics, |this| {
621 intravisit::walk_item(this, item);
622 });
623 self.missing_named_lifetime_spots.pop();
624 }
625
626 hir::ItemKind::ExternCrate(_)
627 | hir::ItemKind::Use(..)
628 | hir::ItemKind::Macro(..)
629 | hir::ItemKind::Mod(..)
630 | hir::ItemKind::ForeignMod { .. }
631 | hir::ItemKind::GlobalAsm(..) => {
632 // These sorts of items have no lifetime parameters at all.
633 intravisit::walk_item(self, item);
634 }
635 hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
636 // No lifetime parameters, but implied 'static.
637 let scope = Scope::Elision { elide: Elide::Exact(Region::Static), s: ROOT_SCOPE };
638 self.with(scope, |this| intravisit::walk_item(this, item));
639 }
640 hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
641 // Opaque types are visited when we visit the
642 // `TyKind::OpaqueDef`, so that they have the lifetimes from
643 // their parent opaque_ty in scope.
644 //
645 // The core idea here is that since OpaqueTys are generated with the impl Trait as
646 // their owner, we can keep going until we find the Item that owns that. We then
647 // conservatively add all resolved lifetimes. Otherwise we run into problems in
648 // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
649 for (_hir_id, node) in
650 self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id))
651 {
652 match node {
653 hir::Node::Item(parent_item) => {
654 let resolved_lifetimes: &ResolveLifetimes =
655 self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id));
656 // We need to add *all* deps, since opaque tys may want them from *us*
657 for (&owner, defs) in resolved_lifetimes.defs.iter() {
658 defs.iter().for_each(|(&local_id, region)| {
659 self.map.defs.insert(hir::HirId { owner, local_id }, *region);
660 });
661 }
662 for (&owner, late_bound_vars) in
663 resolved_lifetimes.late_bound_vars.iter()
664 {
665 late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
666 self.map.late_bound_vars.insert(
667 hir::HirId { owner, local_id },
668 late_bound_vars.clone(),
669 );
670 });
671 }
672 break;
673 }
674 hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"),
675 _ => {}
676 }
677 }
678 }
679 hir::ItemKind::TyAlias(_, ref generics)
680 | hir::ItemKind::Enum(_, ref generics)
681 | hir::ItemKind::Struct(_, ref generics)
682 | hir::ItemKind::Union(_, ref generics)
683 | hir::ItemKind::Trait(_, _, ref generics, ..)
684 | hir::ItemKind::TraitAlias(ref generics, ..)
685 | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
686 self.missing_named_lifetime_spots.push(generics.into());
687
688 // These kinds of items have only early-bound lifetime parameters.
689 let mut index = if sub_items_have_self_param(&item.kind) {
690 1 // Self comes before lifetimes
691 } else {
692 0
693 };
694 let mut non_lifetime_count = 0;
695 let lifetimes = generics
696 .params
697 .iter()
698 .filter_map(|param| match param.kind {
699 GenericParamKind::Lifetime { .. } => {
700 Some(Region::early(self.tcx.hir(), &mut index, param))
701 }
702 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
703 non_lifetime_count += 1;
704 None
705 }
706 })
707 .collect();
708 self.map.late_bound_vars.insert(item.hir_id(), vec![]);
709 let scope = Scope::Binder {
710 hir_id: item.hir_id(),
711 lifetimes,
712 next_early_index: index + non_lifetime_count,
713 opaque_type_parent: true,
714 scope_type: BinderScopeType::Normal,
715 s: ROOT_SCOPE,
716 allow_late_bound: false,
717 where_bound_origin: None,
718 };
719 self.with(scope, |this| {
720 let scope = Scope::TraitRefBoundary { s: this.scope };
721 this.with(scope, |this| {
722 intravisit::walk_item(this, item);
723 });
724 });
725 self.missing_named_lifetime_spots.pop();
726 }
727 }
728 }
729
730 fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
731 match item.kind {
732 hir::ForeignItemKind::Fn(_, _, ref generics) => {
733 self.visit_early_late(None, item.hir_id(), generics, |this| {
734 intravisit::walk_foreign_item(this, item);
735 })
736 }
737 hir::ForeignItemKind::Static(..) => {
738 intravisit::walk_foreign_item(self, item);
739 }
740 hir::ForeignItemKind::Type => {
741 intravisit::walk_foreign_item(self, item);
742 }
743 }
744 }
745
746 #[tracing::instrument(level = "debug", skip(self))]
747 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
748 match ty.kind {
749 hir::TyKind::BareFn(ref c) => {
750 let next_early_index = self.next_early_index();
751 let lifetime_span: Option<Span> =
752 c.generic_params.iter().rev().find_map(|param| match param.kind {
753 GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } => {
754 Some(param.span)
755 }
756 _ => None,
757 });
758 let (span, span_type) = if let Some(span) = lifetime_span {
759 (span.shrink_to_hi(), ForLifetimeSpanType::TypeTail)
760 } else {
761 (ty.span.shrink_to_lo(), ForLifetimeSpanType::TypeEmpty)
762 };
763 self.missing_named_lifetime_spots
764 .push(MissingLifetimeSpot::HigherRanked { span, span_type });
765 let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
766 .generic_params
767 .iter()
768 .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
769 .enumerate()
770 .map(|(late_bound_idx, param)| {
771 let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
772 let r = late_region_as_bound_region(self.tcx, &pair.1);
773 (pair, r)
774 })
775 .unzip();
776 self.map.late_bound_vars.insert(ty.hir_id, binders);
777 let scope = Scope::Binder {
778 hir_id: ty.hir_id,
779 lifetimes,
780 s: self.scope,
781 next_early_index,
782 opaque_type_parent: false,
783 scope_type: BinderScopeType::Normal,
784 allow_late_bound: true,
785 where_bound_origin: None,
786 };
787 self.with(scope, |this| {
788 // a bare fn has no bounds, so everything
789 // contained within is scoped within its binder.
790 intravisit::walk_ty(this, ty);
791 });
792 self.missing_named_lifetime_spots.pop();
793 }
794 hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
795 debug!(?bounds, ?lifetime, "TraitObject");
796 let scope = Scope::TraitRefBoundary { s: self.scope };
797 self.with(scope, |this| {
798 for bound in bounds {
799 this.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
800 }
801 });
802 match lifetime.name {
803 LifetimeName::Implicit => {
804 // For types like `dyn Foo`, we should
805 // generate a special form of elided.
806 span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
807 }
808 LifetimeName::ImplicitObjectLifetimeDefault => {
809 // If the user does not write *anything*, we
810 // use the object lifetime defaulting
811 // rules. So e.g., `Box<dyn Debug>` becomes
812 // `Box<dyn Debug + 'static>`.
813 self.resolve_object_lifetime_default(lifetime)
814 }
815 LifetimeName::Underscore => {
816 // If the user writes `'_`, we use the *ordinary* elision
817 // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
818 // resolved the same as the `'_` in `&'_ Foo`.
819 //
820 // cc #48468
821 self.resolve_elided_lifetimes(&[lifetime])
822 }
823 LifetimeName::Param(..) | LifetimeName::Static => {
824 // If the user wrote an explicit name, use that.
825 self.visit_lifetime(lifetime);
826 }
827 LifetimeName::Error => {}
828 }
829 }
830 hir::TyKind::Rptr(ref lifetime_ref, ref mt) => {
831 self.visit_lifetime(lifetime_ref);
832 let scope = Scope::ObjectLifetimeDefault {
833 lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(),
834 s: self.scope,
835 };
836 self.with(scope, |this| this.visit_ty(&mt.ty));
837 }
838 hir::TyKind::OpaqueDef(item_id, lifetimes) => {
839 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
840 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
841 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
842 // ^ ^ this gets resolved in the scope of
843 // the opaque_ty generics
844 let opaque_ty = self.tcx.hir().item(item_id);
845 let (generics, bounds) = match opaque_ty.kind {
846 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
847 origin: hir::OpaqueTyOrigin::TyAlias,
848 ..
849 }) => {
850 intravisit::walk_ty(self, ty);
851
852 // Elided lifetimes are not allowed in non-return
853 // position impl Trait
854 let scope = Scope::TraitRefBoundary { s: self.scope };
855 self.with(scope, |this| {
856 let scope = Scope::Elision { elide: Elide::Forbid, s: this.scope };
857 this.with(scope, |this| {
858 intravisit::walk_item(this, opaque_ty);
859 })
860 });
861
862 return;
863 }
864 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
865 origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
866 ref generics,
867 bounds,
868 ..
869 }) => (generics, bounds),
870 ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
871 };
872
873 // Resolve the lifetimes that are applied to the opaque type.
874 // These are resolved in the current scope.
875 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
876 // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
877 // ^ ^this gets resolved in the current scope
878 for lifetime in lifetimes {
879 let hir::GenericArg::Lifetime(lifetime) = lifetime else {
880 continue
881 };
882 self.visit_lifetime(lifetime);
883
884 // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
885 // and ban them. Type variables instantiated inside binders aren't
886 // well-supported at the moment, so this doesn't work.
887 // In the future, this should be fixed and this error should be removed.
888 let def = self.map.defs.get(&lifetime.hir_id).cloned();
889 let Some(Region::LateBound(_, _, def_id)) = def else {
890 continue
891 };
892 let Some(def_id) = def_id.as_local() else {
893 continue
894 };
895 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
896 // Ensure that the parent of the def is an item, not HRTB
897 let parent_id = self.tcx.hir().get_parent_node(hir_id);
898 if !parent_id.is_owner() {
899 if !self.trait_definition_only {
900 struct_span_err!(
901 self.tcx.sess,
902 lifetime.span,
903 E0657,
904 "`impl Trait` can only capture lifetimes \
905 bound at the fn or impl level"
906 )
907 .emit();
908 }
909 self.uninsert_lifetime_on_error(lifetime, def.unwrap());
910 }
911 if let hir::Node::Item(hir::Item {
912 kind: hir::ItemKind::OpaqueTy { .. }, ..
913 }) = self.tcx.hir().get(parent_id)
914 {
915 if !self.trait_definition_only {
916 let mut err = self.tcx.sess.struct_span_err(
917 lifetime.span,
918 "higher kinded lifetime bounds on nested opaque types are not supported yet",
919 );
920 err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
921 err.emit();
922 }
923 self.uninsert_lifetime_on_error(lifetime, def.unwrap());
924 }
925 }
926
927 // We want to start our early-bound indices at the end of the parent scope,
928 // not including any parent `impl Trait`s.
929 let mut index = self.next_early_index_for_opaque_type();
930 debug!(?index);
931
932 let mut elision = None;
933 let mut lifetimes = FxIndexMap::default();
934 let mut non_lifetime_count = 0;
935 for param in generics.params {
936 match param.kind {
937 GenericParamKind::Lifetime { .. } => {
938 let (def_id, reg) = Region::early(self.tcx.hir(), &mut index, &param);
939 if let hir::ParamName::Plain(Ident {
940 name: kw::UnderscoreLifetime,
941 ..
942 }) = param.name
943 {
944 // Pick the elided lifetime "definition" if one exists
945 // and use it to make an elision scope.
946 elision = Some(reg);
947 } else {
948 lifetimes.insert(def_id, reg);
949 }
950 }
951 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
952 non_lifetime_count += 1;
953 }
954 }
955 }
956 let next_early_index = index + non_lifetime_count;
957 self.map.late_bound_vars.insert(ty.hir_id, vec![]);
958
959 if let Some(elision_region) = elision {
960 let scope =
961 Scope::Elision { elide: Elide::Exact(elision_region), s: self.scope };
962 self.with(scope, |this| {
963 let scope = Scope::Binder {
964 hir_id: ty.hir_id,
965 lifetimes,
966 next_early_index,
967 s: this.scope,
968 opaque_type_parent: false,
969 scope_type: BinderScopeType::Normal,
970 allow_late_bound: false,
971 where_bound_origin: None,
972 };
973 this.with(scope, |this| {
974 this.visit_generics(generics);
975 let scope = Scope::TraitRefBoundary { s: this.scope };
976 this.with(scope, |this| {
977 for bound in bounds {
978 this.visit_param_bound(bound);
979 }
980 })
981 });
982 });
983 } else {
984 let scope = Scope::Binder {
985 hir_id: ty.hir_id,
986 lifetimes,
987 next_early_index,
988 s: self.scope,
989 opaque_type_parent: false,
990 scope_type: BinderScopeType::Normal,
991 allow_late_bound: false,
992 where_bound_origin: None,
993 };
994 self.with(scope, |this| {
995 let scope = Scope::TraitRefBoundary { s: this.scope };
996 this.with(scope, |this| {
997 this.visit_generics(generics);
998 for bound in bounds {
999 this.visit_param_bound(bound);
1000 }
1001 })
1002 });
1003 }
1004 }
1005 _ => intravisit::walk_ty(self, ty),
1006 }
1007 }
1008
1009 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
1010 use self::hir::TraitItemKind::*;
1011 match trait_item.kind {
1012 Fn(_, _) => {
1013 self.missing_named_lifetime_spots.push((&trait_item.generics).into());
1014 let tcx = self.tcx;
1015 self.visit_early_late(
1016 Some(tcx.hir().get_parent_item(trait_item.hir_id())),
1017 trait_item.hir_id(),
1018 &trait_item.generics,
1019 |this| intravisit::walk_trait_item(this, trait_item),
1020 );
1021 self.missing_named_lifetime_spots.pop();
1022 }
1023 Type(bounds, ref ty) => {
1024 self.missing_named_lifetime_spots.push((&trait_item.generics).into());
1025 let generics = &trait_item.generics;
1026 let mut index = self.next_early_index();
1027 debug!("visit_ty: index = {}", index);
1028 let mut non_lifetime_count = 0;
1029 let lifetimes = generics
1030 .params
1031 .iter()
1032 .filter_map(|param| match param.kind {
1033 GenericParamKind::Lifetime { .. } => {
1034 Some(Region::early(self.tcx.hir(), &mut index, param))
1035 }
1036 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1037 non_lifetime_count += 1;
1038 None
1039 }
1040 })
1041 .collect();
1042 self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
1043 let scope = Scope::Binder {
1044 hir_id: trait_item.hir_id(),
1045 lifetimes,
1046 next_early_index: index + non_lifetime_count,
1047 s: self.scope,
1048 opaque_type_parent: true,
1049 scope_type: BinderScopeType::Normal,
1050 allow_late_bound: false,
1051 where_bound_origin: None,
1052 };
1053 self.with(scope, |this| {
1054 let scope = Scope::TraitRefBoundary { s: this.scope };
1055 this.with(scope, |this| {
1056 this.visit_generics(generics);
1057 for bound in bounds {
1058 this.visit_param_bound(bound);
1059 }
1060 if let Some(ty) = ty {
1061 this.visit_ty(ty);
1062 }
1063 })
1064 });
1065 self.missing_named_lifetime_spots.pop();
1066 }
1067 Const(_, _) => {
1068 // Only methods and types support generics.
1069 assert!(trait_item.generics.params.is_empty());
1070 self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
1071 intravisit::walk_trait_item(self, trait_item);
1072 self.missing_named_lifetime_spots.pop();
1073 }
1074 }
1075 }
1076
1077 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
1078 use self::hir::ImplItemKind::*;
1079 match impl_item.kind {
1080 Fn(..) => {
1081 self.missing_named_lifetime_spots.push((&impl_item.generics).into());
1082 let tcx = self.tcx;
1083 self.visit_early_late(
1084 Some(tcx.hir().get_parent_item(impl_item.hir_id())),
1085 impl_item.hir_id(),
1086 &impl_item.generics,
1087 |this| intravisit::walk_impl_item(this, impl_item),
1088 );
1089 self.missing_named_lifetime_spots.pop();
1090 }
1091 TyAlias(ref ty) => {
1092 let generics = &impl_item.generics;
1093 self.missing_named_lifetime_spots.push(generics.into());
1094 let mut index = self.next_early_index();
1095 let mut non_lifetime_count = 0;
1096 debug!("visit_ty: index = {}", index);
1097 let lifetimes: FxIndexMap<LocalDefId, Region> = generics
1098 .params
1099 .iter()
1100 .filter_map(|param| match param.kind {
1101 GenericParamKind::Lifetime { .. } => {
1102 Some(Region::early(self.tcx.hir(), &mut index, param))
1103 }
1104 GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => {
1105 non_lifetime_count += 1;
1106 None
1107 }
1108 })
1109 .collect();
1110 self.map.late_bound_vars.insert(ty.hir_id, vec![]);
1111 let scope = Scope::Binder {
1112 hir_id: ty.hir_id,
1113 lifetimes,
1114 next_early_index: index + non_lifetime_count,
1115 s: self.scope,
1116 opaque_type_parent: true,
1117 scope_type: BinderScopeType::Normal,
1118 allow_late_bound: true,
1119 where_bound_origin: None,
1120 };
1121 self.with(scope, |this| {
1122 let scope = Scope::TraitRefBoundary { s: this.scope };
1123 this.with(scope, |this| {
1124 this.visit_generics(generics);
1125 this.visit_ty(ty);
1126 })
1127 });
1128 self.missing_named_lifetime_spots.pop();
1129 }
1130 Const(_, _) => {
1131 // Only methods and types support generics.
1132 assert!(impl_item.generics.params.is_empty());
1133 self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
1134 intravisit::walk_impl_item(self, impl_item);
1135 self.missing_named_lifetime_spots.pop();
1136 }
1137 }
1138 }
1139
1140 #[tracing::instrument(level = "debug", skip(self))]
1141 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1142 match lifetime_ref.name {
1143 hir::LifetimeName::ImplicitObjectLifetimeDefault
1144 | hir::LifetimeName::Implicit
1145 | hir::LifetimeName::Underscore => self.resolve_elided_lifetimes(&[lifetime_ref]),
1146 hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
1147 hir::LifetimeName::Param(param_def_id, _) => {
1148 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
1149 }
1150 // If we've already reported an error, just ignore `lifetime_ref`.
1151 hir::LifetimeName::Error => {}
1152 }
1153 }
1154
1155 fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) {
1156 for (i, segment) in path.segments.iter().enumerate() {
1157 let depth = path.segments.len() - i - 1;
1158 if let Some(ref args) = segment.args {
1159 self.visit_segment_args(path.res, depth, args);
1160 }
1161 }
1162 }
1163
1164 fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
1165 let output = match fd.output {
1166 hir::FnRetTy::DefaultReturn(_) => None,
1167 hir::FnRetTy::Return(ref ty) => Some(&**ty),
1168 };
1169 self.visit_fn_like_elision(&fd.inputs, output);
1170 }
1171
1172 fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
1173 let scope = Scope::TraitRefBoundary { s: self.scope };
1174 self.with(scope, |this| {
1175 for param in generics.params {
1176 match param.kind {
1177 GenericParamKind::Lifetime { .. } => {}
1178 GenericParamKind::Type { ref default, .. } => {
1179 if let Some(ref ty) = default {
1180 this.visit_ty(&ty);
1181 }
1182 }
1183 GenericParamKind::Const { ref ty, default } => {
1184 this.visit_ty(&ty);
1185 if let Some(default) = default {
1186 this.visit_body(this.tcx.hir().body(default.body));
1187 }
1188 }
1189 }
1190 }
1191 for predicate in generics.predicates {
1192 match predicate {
1193 &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1194 ref bounded_ty,
1195 bounds,
1196 ref bound_generic_params,
1197 origin,
1198 ..
1199 }) => {
1200 let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
1201 bound_generic_params
1202 .iter()
1203 .filter(|param| {
1204 matches!(param.kind, GenericParamKind::Lifetime { .. })
1205 })
1206 .enumerate()
1207 .map(|(late_bound_idx, param)| {
1208 let pair =
1209 Region::late(late_bound_idx as u32, this.tcx.hir(), param);
1210 let r = late_region_as_bound_region(this.tcx, &pair.1);
1211 (pair, r)
1212 })
1213 .unzip();
1214 this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
1215 let next_early_index = this.next_early_index();
1216 // Even if there are no lifetimes defined here, we still wrap it in a binder
1217 // scope. If there happens to be a nested poly trait ref (an error), that
1218 // will be `Concatenating` anyways, so we don't have to worry about the depth
1219 // being wrong.
1220 let scope = Scope::Binder {
1221 hir_id: bounded_ty.hir_id,
1222 lifetimes,
1223 s: this.scope,
1224 next_early_index,
1225 opaque_type_parent: false,
1226 scope_type: BinderScopeType::Normal,
1227 allow_late_bound: true,
1228 where_bound_origin: Some(origin),
1229 };
1230 this.with(scope, |this| {
1231 this.visit_ty(&bounded_ty);
1232 walk_list!(this, visit_param_bound, bounds);
1233 })
1234 }
1235 &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
1236 ref lifetime,
1237 bounds,
1238 ..
1239 }) => {
1240 this.visit_lifetime(lifetime);
1241 walk_list!(this, visit_param_bound, bounds);
1242
1243 if lifetime.name != hir::LifetimeName::Static {
1244 for bound in bounds {
1245 let hir::GenericBound::Outlives(ref lt) = bound else {
1246 continue;
1247 };
1248 if lt.name != hir::LifetimeName::Static {
1249 continue;
1250 }
1251 this.insert_lifetime(lt, Region::Static);
1252 this.tcx
1253 .sess
1254 .struct_span_warn(
1255 lifetime.span,
1256 &format!(
1257 "unnecessary lifetime parameter `{}`",
1258 lifetime.name.ident(),
1259 ),
1260 )
1261 .help(&format!(
1262 "you can use the `'static` lifetime directly, in place of `{}`",
1263 lifetime.name.ident(),
1264 ))
1265 .emit();
1266 }
1267 }
1268 }
1269 &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
1270 ref lhs_ty,
1271 ref rhs_ty,
1272 ..
1273 }) => {
1274 this.visit_ty(lhs_ty);
1275 this.visit_ty(rhs_ty);
1276 }
1277 }
1278 }
1279 })
1280 }
1281
1282 fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
1283 match bound {
1284 hir::GenericBound::LangItemTrait(_, _, hir_id, _) => {
1285 // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go
1286 // through the regular poly trait ref code, so we don't get another
1287 // chance to introduce a binder. For now, I'm keeping the existing logic
1288 // of "if there isn't a Binder scope above us, add one", but I
1289 // imagine there's a better way to go about this.
1290 let (binders, scope_type) = self.poly_trait_ref_binder_info();
1291
1292 self.map.late_bound_vars.insert(*hir_id, binders);
1293 let scope = Scope::Binder {
1294 hir_id: *hir_id,
1295 lifetimes: FxIndexMap::default(),
1296 s: self.scope,
1297 next_early_index: self.next_early_index(),
1298 opaque_type_parent: false,
1299 scope_type,
1300 allow_late_bound: true,
1301 where_bound_origin: None,
1302 };
1303 self.with(scope, |this| {
1304 intravisit::walk_param_bound(this, bound);
1305 });
1306 }
1307 _ => intravisit::walk_param_bound(self, bound),
1308 }
1309 }
1310
1311 fn visit_poly_trait_ref(
1312 &mut self,
1313 trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
1314 _modifier: hir::TraitBoundModifier,
1315 ) {
1316 debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
1317
1318 let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref);
1319
1320 let next_early_index = self.next_early_index();
1321 let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
1322
1323 let initial_bound_vars = binders.len() as u32;
1324 let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
1325 let binders_iter = trait_ref
1326 .bound_generic_params
1327 .iter()
1328 .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
1329 .enumerate()
1330 .map(|(late_bound_idx, param)| {
1331 let pair =
1332 Region::late(initial_bound_vars + late_bound_idx as u32, self.tcx.hir(), param);
1333 let r = late_region_as_bound_region(self.tcx, &pair.1);
1334 lifetimes.insert(pair.0, pair.1);
1335 r
1336 });
1337 binders.extend(binders_iter);
1338
1339 debug!(?binders);
1340 self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
1341
1342 // Always introduce a scope here, even if this is in a where clause and
1343 // we introduced the binders around the bounded Ty. In that case, we
1344 // just reuse the concatenation functionality also present in nested trait
1345 // refs.
1346 let scope = Scope::Binder {
1347 hir_id: trait_ref.trait_ref.hir_ref_id,
1348 lifetimes,
1349 s: self.scope,
1350 next_early_index,
1351 opaque_type_parent: false,
1352 scope_type,
1353 allow_late_bound: true,
1354 where_bound_origin: None,
1355 };
1356 self.with(scope, |this| {
1357 walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
1358 this.visit_trait_ref(&trait_ref.trait_ref);
1359 });
1360
1361 if should_pop_missing_lt {
1362 self.missing_named_lifetime_spots.pop();
1363 }
1364 }
1365 }
1366
1367 fn compute_object_lifetime_defaults<'tcx>(
1368 tcx: TyCtxt<'tcx>,
1369 item: &hir::Item<'_>,
1370 ) -> Option<&'tcx [ObjectLifetimeDefault]> {
1371 match item.kind {
1372 hir::ItemKind::Struct(_, ref generics)
1373 | hir::ItemKind::Union(_, ref generics)
1374 | hir::ItemKind::Enum(_, ref generics)
1375 | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
1376 ref generics,
1377 origin: hir::OpaqueTyOrigin::TyAlias,
1378 ..
1379 })
1380 | hir::ItemKind::TyAlias(_, ref generics)
1381 | hir::ItemKind::Trait(_, _, ref generics, ..) => {
1382 let result = object_lifetime_defaults_for_item(tcx, generics);
1383
1384 // Debugging aid.
1385 let attrs = tcx.hir().attrs(item.hir_id());
1386 if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) {
1387 let object_lifetime_default_reprs: String = result
1388 .iter()
1389 .map(|set| match *set {
1390 Set1::Empty => "BaseDefault".into(),
1391 Set1::One(Region::Static) => "'static".into(),
1392 Set1::One(Region::EarlyBound(mut i, _)) => generics
1393 .params
1394 .iter()
1395 .find_map(|param| match param.kind {
1396 GenericParamKind::Lifetime { .. } => {
1397 if i == 0 {
1398 return Some(param.name.ident().to_string().into());
1399 }
1400 i -= 1;
1401 None
1402 }
1403 _ => None,
1404 })
1405 .unwrap(),
1406 Set1::One(_) => bug!(),
1407 Set1::Many => "Ambiguous".into(),
1408 })
1409 .collect::<Vec<Cow<'static, str>>>()
1410 .join(",");
1411 tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
1412 }
1413
1414 Some(result)
1415 }
1416 _ => None,
1417 }
1418 }
1419
1420 /// Scan the bounds and where-clauses on parameters to extract bounds
1421 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1422 /// for each type parameter.
1423 fn object_lifetime_defaults_for_item<'tcx>(
1424 tcx: TyCtxt<'tcx>,
1425 generics: &hir::Generics<'_>,
1426 ) -> &'tcx [ObjectLifetimeDefault] {
1427 fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound<'_>]) {
1428 for bound in bounds {
1429 if let hir::GenericBound::Outlives(ref lifetime) = *bound {
1430 set.insert(lifetime.name.normalize_to_macros_2_0());
1431 }
1432 }
1433 }
1434
1435 let process_param = |param: &hir::GenericParam<'_>| match param.kind {
1436 GenericParamKind::Lifetime { .. } => None,
1437 GenericParamKind::Type { .. } => {
1438 let mut set = Set1::Empty;
1439
1440 let param_def_id = tcx.hir().local_def_id(param.hir_id);
1441 for predicate in generics.predicates {
1442 // Look for `type: ...` where clauses.
1443 let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue };
1444
1445 // Ignore `for<'a> type: ...` as they can change what
1446 // lifetimes mean (although we could "just" handle it).
1447 if !data.bound_generic_params.is_empty() {
1448 continue;
1449 }
1450
1451 let res = match data.bounded_ty.kind {
1452 hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.res,
1453 _ => continue,
1454 };
1455
1456 if res == Res::Def(DefKind::TyParam, param_def_id.to_def_id()) {
1457 add_bounds(&mut set, &data.bounds);
1458 }
1459 }
1460
1461 Some(match set {
1462 Set1::Empty => Set1::Empty,
1463 Set1::One(name) => {
1464 if name == hir::LifetimeName::Static {
1465 Set1::One(Region::Static)
1466 } else {
1467 generics
1468 .params
1469 .iter()
1470 .filter_map(|param| match param.kind {
1471 GenericParamKind::Lifetime { .. } => {
1472 let param_def_id = tcx.hir().local_def_id(param.hir_id);
1473 Some((
1474 param_def_id,
1475 hir::LifetimeName::Param(param_def_id, param.name),
1476 ))
1477 }
1478 _ => None,
1479 })
1480 .enumerate()
1481 .find(|&(_, (_, lt_name))| lt_name == name)
1482 .map_or(Set1::Many, |(i, (def_id, _))| {
1483 Set1::One(Region::EarlyBound(i as u32, def_id.to_def_id()))
1484 })
1485 }
1486 }
1487 Set1::Many => Set1::Many,
1488 })
1489 }
1490 GenericParamKind::Const { .. } => {
1491 // Generic consts don't impose any constraints.
1492 //
1493 // We still store a dummy value here to allow generic parameters
1494 // in an arbitrary order.
1495 Some(Set1::Empty)
1496 }
1497 };
1498
1499 tcx.arena.alloc_from_iter(generics.params.iter().filter_map(process_param))
1500 }
1501
1502 impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1503 fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1504 where
1505 F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
1506 {
1507 let LifetimeContext { tcx, map, .. } = self;
1508 let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults);
1509 let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots);
1510 let mut this = LifetimeContext {
1511 tcx: *tcx,
1512 map,
1513 scope: &wrap_scope,
1514 trait_definition_only: self.trait_definition_only,
1515 xcrate_object_lifetime_defaults,
1516 missing_named_lifetime_spots,
1517 };
1518 let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
1519 {
1520 let _enter = span.enter();
1521 f(&mut this);
1522 }
1523 self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
1524 self.missing_named_lifetime_spots = this.missing_named_lifetime_spots;
1525 }
1526
1527 /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1528 ///
1529 /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1530 /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1531 /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1532 ///
1533 /// For example:
1534 ///
1535 /// fn foo<'a,'b,'c,T:Trait<'b>>(...)
1536 ///
1537 /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1538 /// lifetimes may be interspersed together.
1539 ///
1540 /// If early bound lifetimes are present, we separate them into their own list (and likewise
1541 /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1542 /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1543 /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1544 /// ordering is not important there.
1545 fn visit_early_late<F>(
1546 &mut self,
1547 parent_id: Option<LocalDefId>,
1548 hir_id: hir::HirId,
1549 generics: &'tcx hir::Generics<'tcx>,
1550 walk: F,
1551 ) where
1552 F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
1553 {
1554 // Find the start of nested early scopes, e.g., in methods.
1555 let mut next_early_index = 0;
1556 if let Some(parent_id) = parent_id {
1557 let parent = self.tcx.hir().expect_item(parent_id);
1558 if sub_items_have_self_param(&parent.kind) {
1559 next_early_index += 1; // Self comes before lifetimes
1560 }
1561 match parent.kind {
1562 hir::ItemKind::Trait(_, _, ref generics, ..)
1563 | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
1564 next_early_index += generics.params.len() as u32;
1565 }
1566 _ => {}
1567 }
1568 }
1569
1570 let mut non_lifetime_count = 0;
1571 let mut named_late_bound_vars = 0;
1572 let lifetimes: FxIndexMap<LocalDefId, Region> = generics
1573 .params
1574 .iter()
1575 .filter_map(|param| match param.kind {
1576 GenericParamKind::Lifetime { .. } => {
1577 if self.tcx.is_late_bound(param.hir_id) {
1578 let late_bound_idx = named_late_bound_vars;
1579 named_late_bound_vars += 1;
1580 Some(Region::late(late_bound_idx, self.tcx.hir(), param))
1581 } else {
1582 Some(Region::early(self.tcx.hir(), &mut next_early_index, param))
1583 }
1584 }
1585 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1586 non_lifetime_count += 1;
1587 None
1588 }
1589 })
1590 .collect();
1591 let next_early_index = next_early_index + non_lifetime_count;
1592
1593 let binders: Vec<_> = generics
1594 .params
1595 .iter()
1596 .filter(|param| {
1597 matches!(param.kind, GenericParamKind::Lifetime { .. })
1598 && self.tcx.is_late_bound(param.hir_id)
1599 })
1600 .enumerate()
1601 .map(|(late_bound_idx, param)| {
1602 let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
1603 late_region_as_bound_region(self.tcx, &pair.1)
1604 })
1605 .collect();
1606 self.map.late_bound_vars.insert(hir_id, binders);
1607 let scope = Scope::Binder {
1608 hir_id,
1609 lifetimes,
1610 next_early_index,
1611 s: self.scope,
1612 opaque_type_parent: true,
1613 scope_type: BinderScopeType::Normal,
1614 allow_late_bound: true,
1615 where_bound_origin: None,
1616 };
1617 self.with(scope, walk);
1618 }
1619
1620 fn next_early_index_helper(&self, only_opaque_type_parent: bool) -> u32 {
1621 let mut scope = self.scope;
1622 loop {
1623 match *scope {
1624 Scope::Root => return 0,
1625
1626 Scope::Binder { next_early_index, opaque_type_parent, .. }
1627 if (!only_opaque_type_parent || opaque_type_parent) =>
1628 {
1629 return next_early_index;
1630 }
1631
1632 Scope::Binder { s, .. }
1633 | Scope::Body { s, .. }
1634 | Scope::Elision { s, .. }
1635 | Scope::ObjectLifetimeDefault { s, .. }
1636 | Scope::Supertrait { s, .. }
1637 | Scope::TraitRefBoundary { s, .. } => scope = s,
1638 }
1639 }
1640 }
1641
1642 /// Returns the next index one would use for an early-bound-region
1643 /// if extending the current scope.
1644 fn next_early_index(&self) -> u32 {
1645 self.next_early_index_helper(true)
1646 }
1647
1648 /// Returns the next index one would use for an `impl Trait` that
1649 /// is being converted into an opaque type alias `impl Trait`. This will be the
1650 /// next early index from the enclosing item, for the most
1651 /// part. See the `opaque_type_parent` field for more info.
1652 fn next_early_index_for_opaque_type(&self) -> u32 {
1653 self.next_early_index_helper(false)
1654 }
1655
1656 #[tracing::instrument(level = "debug", skip(self))]
1657 fn resolve_lifetime_ref(
1658 &mut self,
1659 region_def_id: LocalDefId,
1660 lifetime_ref: &'tcx hir::Lifetime,
1661 ) {
1662 // Walk up the scope chain, tracking the number of fn scopes
1663 // that we pass through, until we find a lifetime with the
1664 // given name or we run out of scopes.
1665 // search.
1666 let mut late_depth = 0;
1667 let mut scope = self.scope;
1668 let mut outermost_body = None;
1669 let result = loop {
1670 match *scope {
1671 Scope::Body { id, s } => {
1672 outermost_body = Some(id);
1673 scope = s;
1674 }
1675
1676 Scope::Root => {
1677 break None;
1678 }
1679
1680 Scope::Binder { ref lifetimes, scope_type, s, .. } => {
1681 if let Some(&def) = lifetimes.get(&region_def_id) {
1682 break Some(def.shifted(late_depth));
1683 }
1684 match scope_type {
1685 BinderScopeType::Normal => late_depth += 1,
1686 BinderScopeType::Concatenating => {}
1687 }
1688 scope = s;
1689 }
1690
1691 Scope::Elision { s, .. }
1692 | Scope::ObjectLifetimeDefault { s, .. }
1693 | Scope::Supertrait { s, .. }
1694 | Scope::TraitRefBoundary { s, .. } => {
1695 scope = s;
1696 }
1697 }
1698 };
1699
1700 if let Some(mut def) = result {
1701 if let Region::EarlyBound(..) = def {
1702 // Do not free early-bound regions, only late-bound ones.
1703 } else if let Some(body_id) = outermost_body {
1704 let fn_id = self.tcx.hir().body_owner(body_id);
1705 match self.tcx.hir().get(fn_id) {
1706 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. })
1707 | Node::TraitItem(&hir::TraitItem {
1708 kind: hir::TraitItemKind::Fn(..), ..
1709 })
1710 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
1711 let scope = self.tcx.hir().local_def_id(fn_id);
1712 def = Region::Free(scope.to_def_id(), def.id().unwrap());
1713 }
1714 _ => {}
1715 }
1716 }
1717
1718 self.insert_lifetime(lifetime_ref, def);
1719 return;
1720 }
1721
1722 // We may fail to resolve higher-ranked lifetimes that are mentionned by APIT.
1723 // AST-based resolution does not care for impl-trait desugaring, which are the
1724 // responibility of lowering. This may create a mismatch between the resolution
1725 // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1726 // ```
1727 // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1728 // ```
1729 //
1730 // In such case, walk back the binders to diagnose it properly.
1731 let mut scope = self.scope;
1732 loop {
1733 match *scope {
1734 Scope::Binder {
1735 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1736 } => {
1737 let mut err = self.tcx.sess.struct_span_err(
1738 lifetime_ref.span,
1739 "`impl Trait` can only mention lifetimes bound at the fn or impl level",
1740 );
1741 err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1742 err.emit();
1743 return;
1744 }
1745 Scope::Root => break,
1746 Scope::Binder { s, .. }
1747 | Scope::Body { s, .. }
1748 | Scope::Elision { s, .. }
1749 | Scope::ObjectLifetimeDefault { s, .. }
1750 | Scope::Supertrait { s, .. }
1751 | Scope::TraitRefBoundary { s, .. } => {
1752 scope = s;
1753 }
1754 }
1755 }
1756
1757 self.tcx.sess.delay_span_bug(
1758 lifetime_ref.span,
1759 &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1760 );
1761 }
1762
1763 fn visit_segment_args(
1764 &mut self,
1765 res: Res,
1766 depth: usize,
1767 generic_args: &'tcx hir::GenericArgs<'tcx>,
1768 ) {
1769 debug!(
1770 "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})",
1771 res, depth, generic_args,
1772 );
1773
1774 if generic_args.parenthesized {
1775 self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty()));
1776 return;
1777 }
1778
1779 let mut elide_lifetimes = true;
1780 let lifetimes: Vec<_> = generic_args
1781 .args
1782 .iter()
1783 .filter_map(|arg| match arg {
1784 hir::GenericArg::Lifetime(lt) => {
1785 if !lt.is_elided() {
1786 elide_lifetimes = false;
1787 }
1788 Some(lt)
1789 }
1790 _ => None,
1791 })
1792 .collect();
1793 // We short-circuit here if all are elided in order to pluralize
1794 // possible errors
1795 if elide_lifetimes {
1796 self.resolve_elided_lifetimes(&lifetimes);
1797 } else {
1798 lifetimes.iter().for_each(|lt| self.visit_lifetime(lt));
1799 }
1800
1801 // Figure out if this is a type/trait segment,
1802 // which requires object lifetime defaults.
1803 let parent_def_id = |this: &mut Self, def_id: DefId| {
1804 let def_key = this.tcx.def_key(def_id);
1805 DefId { krate: def_id.krate, index: def_key.parent.expect("missing parent") }
1806 };
1807 let type_def_id = match res {
1808 Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(parent_def_id(self, def_id)),
1809 Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(parent_def_id(self, def_id)),
1810 Res::Def(
1811 DefKind::Struct
1812 | DefKind::Union
1813 | DefKind::Enum
1814 | DefKind::TyAlias
1815 | DefKind::Trait,
1816 def_id,
1817 ) if depth == 0 => Some(def_id),
1818 _ => None,
1819 };
1820
1821 debug!("visit_segment_args: type_def_id={:?}", type_def_id);
1822
1823 // Compute a vector of defaults, one for each type parameter,
1824 // per the rules given in RFCs 599 and 1156. Example:
1825 //
1826 // ```rust
1827 // struct Foo<'a, T: 'a, U> { }
1828 // ```
1829 //
1830 // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1831 // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1832 // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1833 // such bound).
1834 //
1835 // Therefore, we would compute `object_lifetime_defaults` to a
1836 // vector like `['x, 'static]`. Note that the vector only
1837 // includes type parameters.
1838 let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1839 let in_body = {
1840 let mut scope = self.scope;
1841 loop {
1842 match *scope {
1843 Scope::Root => break false,
1844
1845 Scope::Body { .. } => break true,
1846
1847 Scope::Binder { s, .. }
1848 | Scope::Elision { s, .. }
1849 | Scope::ObjectLifetimeDefault { s, .. }
1850 | Scope::Supertrait { s, .. }
1851 | Scope::TraitRefBoundary { s, .. } => {
1852 scope = s;
1853 }
1854 }
1855 }
1856 };
1857
1858 let map = &self.map;
1859 let set_to_region = |set: &ObjectLifetimeDefault| match *set {
1860 Set1::Empty => {
1861 if in_body {
1862 None
1863 } else {
1864 Some(Region::Static)
1865 }
1866 }
1867 Set1::One(r) => {
1868 let lifetimes = generic_args.args.iter().filter_map(|arg| match arg {
1869 GenericArg::Lifetime(lt) => Some(lt),
1870 _ => None,
1871 });
1872 r.subst(lifetimes, map)
1873 }
1874 Set1::Many => None,
1875 };
1876 if let Some(def_id) = def_id.as_local() {
1877 let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
1878 self.tcx
1879 .object_lifetime_defaults(id.owner)
1880 .unwrap()
1881 .iter()
1882 .map(set_to_region)
1883 .collect()
1884 } else {
1885 let tcx = self.tcx;
1886 self.xcrate_object_lifetime_defaults
1887 .entry(def_id)
1888 .or_insert_with(|| {
1889 tcx.generics_of(def_id)
1890 .params
1891 .iter()
1892 .filter_map(|param| match param.kind {
1893 GenericParamDefKind::Type { object_lifetime_default, .. } => {
1894 Some(object_lifetime_default)
1895 }
1896 GenericParamDefKind::Const { .. } => Some(Set1::Empty),
1897 GenericParamDefKind::Lifetime => None,
1898 })
1899 .collect()
1900 })
1901 .iter()
1902 .map(set_to_region)
1903 .collect()
1904 }
1905 });
1906
1907 debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults);
1908
1909 let mut i = 0;
1910 for arg in generic_args.args {
1911 match arg {
1912 GenericArg::Lifetime(_) => {}
1913 GenericArg::Type(ty) => {
1914 if let Some(&lt) = object_lifetime_defaults.get(i) {
1915 let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1916 self.with(scope, |this| this.visit_ty(ty));
1917 } else {
1918 self.visit_ty(ty);
1919 }
1920 i += 1;
1921 }
1922 GenericArg::Const(ct) => {
1923 self.visit_anon_const(&ct.value);
1924 i += 1;
1925 }
1926 GenericArg::Infer(inf) => {
1927 self.visit_id(inf.hir_id);
1928 i += 1;
1929 }
1930 }
1931 }
1932
1933 // Hack: when resolving the type `XX` in binding like `dyn
1934 // Foo<'b, Item = XX>`, the current object-lifetime default
1935 // would be to examine the trait `Foo` to check whether it has
1936 // a lifetime bound declared on `Item`. e.g., if `Foo` is
1937 // declared like so, then the default object lifetime bound in
1938 // `XX` should be `'b`:
1939 //
1940 // ```rust
1941 // trait Foo<'a> {
1942 // type Item: 'a;
1943 // }
1944 // ```
1945 //
1946 // but if we just have `type Item;`, then it would be
1947 // `'static`. However, we don't get all of this logic correct.
1948 //
1949 // Instead, we do something hacky: if there are no lifetime parameters
1950 // to the trait, then we simply use a default object lifetime
1951 // bound of `'static`, because there is no other possibility. On the other hand,
1952 // if there ARE lifetime parameters, then we require the user to give an
1953 // explicit bound for now.
1954 //
1955 // This is intended to leave room for us to implement the
1956 // correct behavior in the future.
1957 let has_lifetime_parameter =
1958 generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1959
1960 // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
1961 // in the trait ref `YY<...>` in `Item: YY<...>`.
1962 for binding in generic_args.bindings {
1963 let scope = Scope::ObjectLifetimeDefault {
1964 lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
1965 s: self.scope,
1966 };
1967 if let Some(type_def_id) = type_def_id {
1968 let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
1969 self.tcx,
1970 type_def_id,
1971 binding.ident,
1972 );
1973 self.with(scope, |this| {
1974 let scope = Scope::Supertrait {
1975 lifetimes: lifetimes.unwrap_or_default(),
1976 s: this.scope,
1977 };
1978 this.with(scope, |this| this.visit_assoc_type_binding(binding));
1979 });
1980 } else {
1981 self.with(scope, |this| this.visit_assoc_type_binding(binding));
1982 }
1983 }
1984 }
1985
1986 /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
1987 /// associated type name and starting trait.
1988 /// For example, imagine we have
1989 /// ```ignore (illustrative)
1990 /// trait Foo<'a, 'b> {
1991 /// type As;
1992 /// }
1993 /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
1994 /// trait Bar: for<'b> Bar<'b> {}
1995 /// ```
1996 /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
1997 /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
1998 fn supertrait_hrtb_lifetimes(
1999 tcx: TyCtxt<'tcx>,
2000 def_id: DefId,
2001 assoc_name: Ident,
2002 ) -> Option<Vec<ty::BoundVariableKind>> {
2003 let trait_defines_associated_type_named = |trait_def_id: DefId| {
2004 tcx.associated_items(trait_def_id)
2005 .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
2006 .is_some()
2007 };
2008
2009 use smallvec::{smallvec, SmallVec};
2010 let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
2011 smallvec![(def_id, smallvec![])];
2012 let mut visited: FxHashSet<DefId> = FxHashSet::default();
2013 loop {
2014 let Some((def_id, bound_vars)) = stack.pop() else {
2015 break None;
2016 };
2017 // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
2018 // there being no supertrait HRTBs.
2019 match tcx.def_kind(def_id) {
2020 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {}
2021 _ => break None,
2022 }
2023
2024 if trait_defines_associated_type_named(def_id) {
2025 break Some(bound_vars.into_iter().collect());
2026 }
2027 let predicates =
2028 tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
2029 let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
2030 let bound_predicate = pred.kind();
2031 match bound_predicate.skip_binder() {
2032 ty::PredicateKind::Trait(data) => {
2033 // The order here needs to match what we would get from `subst_supertrait`
2034 let pred_bound_vars = bound_predicate.bound_vars();
2035 let mut all_bound_vars = bound_vars.clone();
2036 all_bound_vars.extend(pred_bound_vars.iter());
2037 let super_def_id = data.trait_ref.def_id;
2038 Some((super_def_id, all_bound_vars))
2039 }
2040 _ => None,
2041 }
2042 });
2043
2044 let obligations = obligations.filter(|o| visited.insert(o.0));
2045 stack.extend(obligations);
2046 }
2047 }
2048
2049 #[tracing::instrument(level = "debug", skip(self))]
2050 fn visit_fn_like_elision(
2051 &mut self,
2052 inputs: &'tcx [hir::Ty<'tcx>],
2053 output: Option<&'tcx hir::Ty<'tcx>>,
2054 ) {
2055 debug!("visit_fn_like_elision: enter");
2056 let mut scope = &*self.scope;
2057 let hir_id = loop {
2058 match scope {
2059 Scope::Binder { hir_id, allow_late_bound: true, .. } => {
2060 break *hir_id;
2061 }
2062 Scope::ObjectLifetimeDefault { ref s, .. }
2063 | Scope::Elision { ref s, .. }
2064 | Scope::Supertrait { ref s, .. }
2065 | Scope::TraitRefBoundary { ref s, .. } => {
2066 scope = *s;
2067 }
2068 Scope::Root
2069 | Scope::Body { .. }
2070 | Scope::Binder { allow_late_bound: false, .. } => {
2071 // See issues #83907 and #83693. Just bail out from looking inside.
2072 // See the issue #95023 for not allowing late bound
2073 self.tcx.sess.delay_span_bug(
2074 rustc_span::DUMMY_SP,
2075 "In fn_like_elision without appropriate scope above",
2076 );
2077 return;
2078 }
2079 }
2080 };
2081 // While not strictly necessary, we gather anon lifetimes *before* actually
2082 // visiting the argument types.
2083 let mut gather = GatherAnonLifetimes { anon_count: 0 };
2084 for input in inputs {
2085 gather.visit_ty(input);
2086 }
2087 trace!(?gather.anon_count);
2088 let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default();
2089 let named_late_bound_vars = late_bound_vars.len() as u32;
2090 late_bound_vars.extend(
2091 (0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))),
2092 );
2093 let arg_scope = Scope::Elision {
2094 elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)),
2095 s: self.scope,
2096 };
2097 self.with(arg_scope, |this| {
2098 for input in inputs {
2099 this.visit_ty(input);
2100 }
2101 });
2102
2103 let Some(output) = output else { return };
2104
2105 debug!("determine output");
2106
2107 // Figure out if there's a body we can get argument names from,
2108 // and whether there's a `self` argument (treated specially).
2109 let mut assoc_item_kind = None;
2110 let mut impl_self = None;
2111 let parent = self.tcx.hir().get_parent_node(output.hir_id);
2112 let body = match self.tcx.hir().get(parent) {
2113 // `fn` definitions and methods.
2114 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(.., body), .. }) => Some(body),
2115
2116 Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => {
2117 if let hir::ItemKind::Trait(.., ref trait_items) =
2118 self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
2119 {
2120 assoc_item_kind =
2121 trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind);
2122 }
2123 match *m {
2124 hir::TraitFn::Required(_) => None,
2125 hir::TraitFn::Provided(body) => Some(body),
2126 }
2127 }
2128
2129 Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => {
2130 if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) =
2131 self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
2132 {
2133 impl_self = Some(self_ty);
2134 assoc_item_kind =
2135 items.iter().find(|ii| ii.id.hir_id() == parent).map(|ii| ii.kind);
2136 }
2137 Some(body)
2138 }
2139
2140 // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
2141 Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None,
2142
2143 Node::TypeBinding(_) if let Node::TraitRef(_) = self.tcx.hir().get(self.tcx.hir().get_parent_node(parent)) => None,
2144
2145 // Everything else (only closures?) doesn't
2146 // actually enjoy elision in return types.
2147 _ => {
2148 self.visit_ty(output);
2149 return;
2150 }
2151 };
2152
2153 let has_self = match assoc_item_kind {
2154 Some(hir::AssocItemKind::Fn { has_self }) => has_self,
2155 _ => false,
2156 };
2157
2158 // In accordance with the rules for lifetime elision, we can determine
2159 // what region to use for elision in the output type in two ways.
2160 // First (determined here), if `self` is by-reference, then the
2161 // implied output region is the region of the self parameter.
2162 if has_self {
2163 struct SelfVisitor<'a> {
2164 map: &'a NamedRegionMap,
2165 impl_self: Option<&'a hir::TyKind<'a>>,
2166 lifetime: Set1<Region>,
2167 }
2168
2169 impl SelfVisitor<'_> {
2170 // Look for `self: &'a Self` - also desugared from `&'a self`,
2171 // and if that matches, use it for elision and return early.
2172 fn is_self_ty(&self, res: Res) -> bool {
2173 if let Res::SelfTy { .. } = res {
2174 return true;
2175 }
2176
2177 // Can't always rely on literal (or implied) `Self` due
2178 // to the way elision rules were originally specified.
2179 if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) =
2180 self.impl_self
2181 {
2182 match path.res {
2183 // Permit the types that unambiguously always
2184 // result in the same type constructor being used
2185 // (it can't differ between `Self` and `self`).
2186 Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _)
2187 | Res::PrimTy(_) => return res == path.res,
2188 _ => {}
2189 }
2190 }
2191
2192 false
2193 }
2194 }
2195
2196 impl<'a> Visitor<'a> for SelfVisitor<'a> {
2197 fn visit_ty(&mut self, ty: &'a hir::Ty<'a>) {
2198 if let hir::TyKind::Rptr(lifetime_ref, ref mt) = ty.kind {
2199 if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.kind
2200 {
2201 if self.is_self_ty(path.res) {
2202 if let Some(lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
2203 self.lifetime.insert(*lifetime);
2204 }
2205 }
2206 }
2207 }
2208 intravisit::walk_ty(self, ty)
2209 }
2210 }
2211
2212 let mut visitor = SelfVisitor {
2213 map: self.map,
2214 impl_self: impl_self.map(|ty| &ty.kind),
2215 lifetime: Set1::Empty,
2216 };
2217 visitor.visit_ty(&inputs[0]);
2218 if let Set1::One(lifetime) = visitor.lifetime {
2219 let scope = Scope::Elision { elide: Elide::Exact(lifetime), s: self.scope };
2220 self.with(scope, |this| this.visit_ty(output));
2221 return;
2222 }
2223 }
2224
2225 // Second, if there was exactly one lifetime (either a substitution or a
2226 // reference) in the arguments, then any anonymous regions in the output
2227 // have that lifetime.
2228 let mut possible_implied_output_region = None;
2229 let mut lifetime_count = 0;
2230 let arg_lifetimes = inputs
2231 .iter()
2232 .enumerate()
2233 .skip(has_self as usize)
2234 .map(|(i, input)| {
2235 let mut gather = GatherLifetimes {
2236 map: self.map,
2237 outer_index: ty::INNERMOST,
2238 have_bound_regions: false,
2239 lifetimes: Default::default(),
2240 };
2241 gather.visit_ty(input);
2242
2243 lifetime_count += gather.lifetimes.len();
2244
2245 if lifetime_count == 1 && gather.lifetimes.len() == 1 {
2246 // there's a chance that the unique lifetime of this
2247 // iteration will be the appropriate lifetime for output
2248 // parameters, so lets store it.
2249 possible_implied_output_region = gather.lifetimes.iter().cloned().next();
2250 }
2251
2252 ElisionFailureInfo {
2253 parent: body,
2254 index: i,
2255 lifetime_count: gather.lifetimes.len(),
2256 have_bound_regions: gather.have_bound_regions,
2257 span: input.span,
2258 }
2259 })
2260 .collect();
2261
2262 let elide = if lifetime_count == 1 {
2263 Elide::Exact(possible_implied_output_region.unwrap())
2264 } else {
2265 Elide::Error(arg_lifetimes)
2266 };
2267
2268 debug!(?elide);
2269
2270 let scope = Scope::Elision { elide, s: self.scope };
2271 self.with(scope, |this| this.visit_ty(output));
2272
2273 struct GatherLifetimes<'a> {
2274 map: &'a NamedRegionMap,
2275 outer_index: ty::DebruijnIndex,
2276 have_bound_regions: bool,
2277 lifetimes: FxHashSet<Region>,
2278 }
2279
2280 impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> {
2281 fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
2282 if let hir::TyKind::BareFn(_) = ty.kind {
2283 self.outer_index.shift_in(1);
2284 }
2285 match ty.kind {
2286 hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
2287 for bound in bounds {
2288 self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
2289 }
2290
2291 // Stay on the safe side and don't include the object
2292 // lifetime default (which may not end up being used).
2293 if !lifetime.is_elided() {
2294 self.visit_lifetime(lifetime);
2295 }
2296 }
2297 _ => {
2298 intravisit::walk_ty(self, ty);
2299 }
2300 }
2301 if let hir::TyKind::BareFn(_) = ty.kind {
2302 self.outer_index.shift_out(1);
2303 }
2304 }
2305
2306 fn visit_generic_param(&mut self, param: &hir::GenericParam<'_>) {
2307 if let hir::GenericParamKind::Lifetime { .. } = param.kind {
2308 // FIXME(eddyb) Do we want this? It only makes a difference
2309 // if this `for<'a>` lifetime parameter is never used.
2310 self.have_bound_regions = true;
2311 }
2312
2313 intravisit::walk_generic_param(self, param);
2314 }
2315
2316 fn visit_poly_trait_ref(
2317 &mut self,
2318 trait_ref: &hir::PolyTraitRef<'_>,
2319 modifier: hir::TraitBoundModifier,
2320 ) {
2321 self.outer_index.shift_in(1);
2322 intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
2323 self.outer_index.shift_out(1);
2324 }
2325
2326 fn visit_param_bound(&mut self, bound: &hir::GenericBound<'_>) {
2327 if let hir::GenericBound::LangItemTrait { .. } = bound {
2328 self.outer_index.shift_in(1);
2329 intravisit::walk_param_bound(self, bound);
2330 self.outer_index.shift_out(1);
2331 } else {
2332 intravisit::walk_param_bound(self, bound);
2333 }
2334 }
2335
2336 fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
2337 if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
2338 match lifetime {
2339 Region::LateBound(debruijn, _, _)
2340 | Region::LateBoundAnon(debruijn, _, _)
2341 if debruijn < self.outer_index =>
2342 {
2343 self.have_bound_regions = true;
2344 }
2345 _ => {
2346 // FIXME(jackh726): nested trait refs?
2347 self.lifetimes.insert(lifetime.shifted_out_to_binder(self.outer_index));
2348 }
2349 }
2350 }
2351 }
2352 }
2353
2354 struct GatherAnonLifetimes {
2355 anon_count: u32,
2356 }
2357 impl<'v> Visitor<'v> for GatherAnonLifetimes {
2358 #[instrument(skip(self), level = "trace")]
2359 fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
2360 // If we enter a `BareFn`, then we enter a *new* binding scope
2361 if let hir::TyKind::BareFn(_) = ty.kind {
2362 return;
2363 }
2364 intravisit::walk_ty(self, ty);
2365 }
2366
2367 fn visit_generic_args(
2368 &mut self,
2369 path_span: Span,
2370 generic_args: &'v hir::GenericArgs<'v>,
2371 ) {
2372 // parenthesized args enter a new elision scope
2373 if generic_args.parenthesized {
2374 return;
2375 }
2376 intravisit::walk_generic_args(self, path_span, generic_args)
2377 }
2378
2379 #[instrument(skip(self), level = "trace")]
2380 fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
2381 if lifetime_ref.is_elided() {
2382 self.anon_count += 1;
2383 }
2384 }
2385 }
2386 }
2387
2388 fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
2389 debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs);
2390
2391 if lifetime_refs.is_empty() {
2392 return;
2393 }
2394
2395 let mut late_depth = 0;
2396 let mut scope = self.scope;
2397 let mut in_scope_lifetimes = FxIndexSet::default();
2398 let error = loop {
2399 match *scope {
2400 // Do not assign any resolution, it will be inferred.
2401 Scope::Body { .. } => return,
2402
2403 Scope::Root => break None,
2404
2405 Scope::Binder { s, ref lifetimes, scope_type, .. } => {
2406 // collect named lifetimes for suggestions
2407 in_scope_lifetimes.extend(lifetimes.keys().copied());
2408 match scope_type {
2409 BinderScopeType::Normal => late_depth += 1,
2410 BinderScopeType::Concatenating => {}
2411 }
2412 scope = s;
2413 }
2414
2415 Scope::Elision {
2416 elide: Elide::FreshLateAnon(named_late_bound_vars, ref counter),
2417 ..
2418 } => {
2419 for lifetime_ref in lifetime_refs {
2420 let lifetime =
2421 Region::late_anon(named_late_bound_vars, counter).shifted(late_depth);
2422
2423 self.insert_lifetime(lifetime_ref, lifetime);
2424 }
2425 return;
2426 }
2427
2428 Scope::Elision { elide: Elide::Exact(l), .. } => {
2429 let lifetime = l.shifted(late_depth);
2430 for lifetime_ref in lifetime_refs {
2431 self.insert_lifetime(lifetime_ref, lifetime);
2432 }
2433 return;
2434 }
2435
2436 Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
2437 let mut scope = s;
2438 loop {
2439 match scope {
2440 Scope::Binder { ref lifetimes, s, .. } => {
2441 // Collect named lifetimes for suggestions.
2442 in_scope_lifetimes.extend(lifetimes.keys().copied());
2443 scope = s;
2444 }
2445 Scope::ObjectLifetimeDefault { ref s, .. }
2446 | Scope::Elision { ref s, .. }
2447 | Scope::TraitRefBoundary { ref s, .. } => {
2448 scope = s;
2449 }
2450 _ => break,
2451 }
2452 }
2453 break Some(&e[..]);
2454 }
2455
2456 Scope::Elision { elide: Elide::Forbid, .. } => break None,
2457
2458 Scope::ObjectLifetimeDefault { s, .. }
2459 | Scope::Supertrait { s, .. }
2460 | Scope::TraitRefBoundary { s, .. } => {
2461 scope = s;
2462 }
2463 }
2464 };
2465
2466 let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
2467 spans.sort();
2468 let mut spans_dedup = spans.clone();
2469 spans_dedup.dedup();
2470 let spans_with_counts: Vec<_> = spans_dedup
2471 .into_iter()
2472 .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count()))
2473 .collect();
2474
2475 let mut err = self.report_missing_lifetime_specifiers(spans.clone(), lifetime_refs.len());
2476
2477 self.add_missing_lifetime_specifiers_label(
2478 &mut err,
2479 spans_with_counts,
2480 in_scope_lifetimes,
2481 error,
2482 );
2483 err.emit();
2484 }
2485
2486 fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2487 debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
2488 let mut late_depth = 0;
2489 let mut scope = self.scope;
2490 let lifetime = loop {
2491 match *scope {
2492 Scope::Binder { s, scope_type, .. } => {
2493 match scope_type {
2494 BinderScopeType::Normal => late_depth += 1,
2495 BinderScopeType::Concatenating => {}
2496 }
2497 scope = s;
2498 }
2499
2500 Scope::Root | Scope::Elision { .. } => break Region::Static,
2501
2502 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
2503
2504 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
2505
2506 Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
2507 scope = s;
2508 }
2509 }
2510 };
2511 self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
2512 }
2513
2514 #[tracing::instrument(level = "debug", skip(self))]
2515 fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
2516 debug!(
2517 node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
2518 span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span)
2519 );
2520 self.map.defs.insert(lifetime_ref.hir_id, def);
2521 }
2522
2523 /// Sometimes we resolve a lifetime, but later find that it is an
2524 /// error (esp. around impl trait). In that case, we remove the
2525 /// entry into `map.defs` so as not to confuse later code.
2526 fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
2527 let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
2528 assert_eq!(old_value, Some(bad_def));
2529 }
2530 }
2531
2532 /// Detects late-bound lifetimes and inserts them into
2533 /// `late_bound`.
2534 ///
2535 /// A region declared on a fn is **late-bound** if:
2536 /// - it is constrained by an argument type;
2537 /// - it does not appear in a where-clause.
2538 ///
2539 /// "Constrained" basically means that it appears in any type but
2540 /// not amongst the inputs to a projection. In other words, `<&'a
2541 /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
2542 fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<LocalDefId>> {
2543 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
2544 let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
2545 let generics = tcx.hir().get_generics(def_id)?;
2546
2547 let mut late_bound = FxIndexSet::default();
2548
2549 let mut constrained_by_input = ConstrainedCollector::default();
2550 for arg_ty in decl.inputs {
2551 constrained_by_input.visit_ty(arg_ty);
2552 }
2553
2554 let mut appears_in_output = AllCollector::default();
2555 intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
2556
2557 debug!(?constrained_by_input.regions);
2558
2559 // Walk the lifetimes that appear in where clauses.
2560 //
2561 // Subtle point: because we disallow nested bindings, we can just
2562 // ignore binders here and scrape up all names we see.
2563 let mut appears_in_where_clause = AllCollector::default();
2564 appears_in_where_clause.visit_generics(generics);
2565 debug!(?appears_in_where_clause.regions);
2566
2567 // Late bound regions are those that:
2568 // - appear in the inputs
2569 // - do not appear in the where-clauses
2570 // - are not implicitly captured by `impl Trait`
2571 for param in generics.params {
2572 match param.kind {
2573 hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
2574
2575 // Neither types nor consts are late-bound.
2576 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2577 }
2578
2579 let param_def_id = tcx.hir().local_def_id(param.hir_id);
2580
2581 // appears in the where clauses? early-bound.
2582 if appears_in_where_clause.regions.contains(&param_def_id) {
2583 continue;
2584 }
2585
2586 // does not appear in the inputs, but appears in the return type? early-bound.
2587 if !constrained_by_input.regions.contains(&param_def_id)
2588 && appears_in_output.regions.contains(&param_def_id)
2589 {
2590 continue;
2591 }
2592
2593 debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
2594
2595 let inserted = late_bound.insert(param_def_id);
2596 assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
2597 }
2598
2599 debug!(?late_bound);
2600 return Some(tcx.arena.alloc(late_bound));
2601
2602 #[derive(Default)]
2603 struct ConstrainedCollector {
2604 regions: FxHashSet<LocalDefId>,
2605 }
2606
2607 impl<'v> Visitor<'v> for ConstrainedCollector {
2608 fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
2609 match ty.kind {
2610 hir::TyKind::Path(
2611 hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2612 ) => {
2613 // ignore lifetimes appearing in associated type
2614 // projections, as they are not *constrained*
2615 // (defined above)
2616 }
2617
2618 hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2619 // consider only the lifetimes on the final
2620 // segment; I am not sure it's even currently
2621 // valid to have them elsewhere, but even if it
2622 // is, those would be potentially inputs to
2623 // projections
2624 if let Some(last_segment) = path.segments.last() {
2625 self.visit_path_segment(path.span, last_segment);
2626 }
2627 }
2628
2629 _ => {
2630 intravisit::walk_ty(self, ty);
2631 }
2632 }
2633 }
2634
2635 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2636 if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
2637 self.regions.insert(def_id);
2638 }
2639 }
2640 }
2641
2642 #[derive(Default)]
2643 struct AllCollector {
2644 regions: FxHashSet<LocalDefId>,
2645 }
2646
2647 impl<'v> Visitor<'v> for AllCollector {
2648 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2649 if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
2650 self.regions.insert(def_id);
2651 }
2652 }
2653 }
2654 }