1 // ignore-tidy-filelength
2 //! Name resolution for lifetimes.
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.
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
;
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}
;
33 fn early(hir_map
: Map
<'_
>, index
: &mut u32, param
: &GenericParam
<'_
>) -> (LocalDefId
, Region
);
35 fn late(index
: u32, hir_map
: Map
<'_
>, param
: &GenericParam
<'_
>) -> (LocalDefId
, Region
);
37 fn late_anon(named_late_bound_vars
: u32, index
: &Cell
<u32>) -> Region
;
39 fn id(&self) -> Option
<DefId
>;
41 fn shifted(self, amount
: u32) -> Region
;
43 fn shifted_out_to_binder(self, binder
: ty
::DebruijnIndex
) -> Region
;
45 fn subst
<'a
, L
>(self, params
: L
, map
: &NamedRegionMap
) -> Option
<Region
>
47 L
: Iterator
<Item
= &'a hir
::Lifetime
>;
50 impl RegionExt
for Region
{
51 fn early(hir_map
: Map
<'_
>, index
: &mut u32, param
: &GenericParam
<'_
>) -> (LocalDefId
, Region
) {
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()))
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
);
63 "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
64 idx
, param
, depth
, def_id
,
66 (def_id
, Region
::LateBound(depth
, idx
, def_id
.to_def_id()))
69 fn late_anon(named_late_bound_vars
: u32, index
: &Cell
<u32>) -> Region
{
72 let depth
= ty
::INNERMOST
;
73 Region
::LateBoundAnon(depth
, named_late_bound_vars
+ i
, i
)
76 fn id(&self) -> Option
<DefId
> {
78 Region
::Static
| Region
::LateBoundAnon(..) => None
,
80 Region
::EarlyBound(_
, id
) | Region
::LateBound(_
, _
, id
) | Region
::Free(_
, id
) => {
86 fn shifted(self, amount
: u32) -> Region
{
88 Region
::LateBound(debruijn
, idx
, id
) => {
89 Region
::LateBound(debruijn
.shifted_in(amount
), idx
, id
)
91 Region
::LateBoundAnon(debruijn
, index
, anon_index
) => {
92 Region
::LateBoundAnon(debruijn
.shifted_in(amount
), index
, anon_index
)
98 fn shifted_out_to_binder(self, binder
: ty
::DebruijnIndex
) -> Region
{
100 Region
::LateBound(debruijn
, index
, id
) => {
101 Region
::LateBound(debruijn
.shifted_out_to_binder(binder
), index
, id
)
103 Region
::LateBoundAnon(debruijn
, index
, anon_index
) => {
104 Region
::LateBoundAnon(debruijn
.shifted_out_to_binder(binder
), index
, anon_index
)
110 fn subst
<'a
, L
>(self, mut params
: L
, map
: &NamedRegionMap
) -> Option
<Region
>
112 L
: Iterator
<Item
= &'a hir
::Lifetime
>,
114 if let Region
::EarlyBound(index
, _
) = self {
115 params
.nth(index
as usize).and_then(|lifetime
| map
.defs
.get(&lifetime
.hir_id
).cloned())
122 /// Maps the id of each lifetime reference to the lifetime decl
123 /// that it corresponds to.
125 /// FIXME. This struct gets converted to a `ResolveLifetimes` for
126 /// actual use. It has the same data, but indexed by `LocalDefId`. This
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
>,
134 // Maps relevant hir items to the bound vars on them. These include:
136 // - function pointers
139 // - bound types (like `T` in `for<'a> T<'a>: Foo`)
140 late_bound_vars
: HirIdMap
<Vec
<ty
::BoundVariableKind
>>,
143 pub(crate) struct LifetimeContext
<'a
, 'tcx
> {
144 pub(crate) tcx
: TyCtxt
<'tcx
>,
145 map
: &'a
mut NamedRegionMap
,
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
,
153 /// Cache for cross-crate per-definition object lifetime defaults.
154 xcrate_object_lifetime_defaults
: DefIdMap
<Vec
<ObjectLifetimeDefault
>>,
156 /// When encountering an undefined named lifetime, we will suggest introducing it in these
158 pub(crate) missing_named_lifetime_spots
: Vec
<MissingLifetimeSpot
<'tcx
>>,
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.
168 /// We use an IndexMap here because we want these lifetimes in order
170 lifetimes
: FxIndexMap
<LocalDefId
, Region
>,
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,
176 /// Whether or not this binder would serve as the parent
177 /// binder for opaque types introduced within. For example:
180 /// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
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
,
191 scope_type
: BinderScopeType
,
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
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
,
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>) {}
210 where_bound_origin
: Option
<hir
::PredicateOrigin
>,
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)`.
222 /// A scope which either determines unspecified lifetimes or errors
223 /// on them (e.g., due to ambiguity). For more details, see `Elide`.
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
>,
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
242 lifetimes
: Vec
<ty
::BoundVariableKind
>,
253 #[derive(Copy, Clone, Debug)]
254 enum BinderScopeType
{
255 /// Any non-concatenating binder scopes.
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`.
269 // A helper struct for debugging scopes without printing parent scopes
270 struct TruncatedScopeDebug
<'a
>(&'a Scope
<'a
>);
272 impl<'a
> fmt
::Debug
for TruncatedScopeDebug
<'a
> {
273 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
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
)
295 Scope
::Body { id, s: _ }
=> {
296 f
.debug_struct("Body").field("id", id
).field("s", &"..").finish()
298 Scope
::Elision { elide, s: _ }
=> {
299 f
.debug_struct("Elision").field("elide", elide
).field("s", &"..").finish()
301 Scope
::ObjectLifetimeDefault { lifetime, s: _ }
=> f
302 .debug_struct("ObjectLifetimeDefault")
303 .field("lifetime", lifetime
)
306 Scope
::Supertrait { lifetimes, s: _ }
=> f
307 .debug_struct("Supertrait")
308 .field("lifetimes", lifetimes
)
311 Scope
::TraitRefBoundary { s: _ }
=> f
.debug_struct("TraitRefBoundary").finish(),
312 Scope
::Root
=> f
.debug_struct("Root").finish(),
317 #[derive(Clone, Debug)]
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.
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.
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
,
343 type ScopeRef
<'a
> = &'a Scope
<'a
>;
345 const ROOT_SCOPE
: ScopeRef
<'
static> = &Scope
::Root
;
347 pub fn provide(providers
: &mut ty
::query
::Providers
) {
348 *providers
= ty
::query
::Providers
{
349 resolve_lifetimes_trait_definition
,
352 named_region_map
: |tcx
, id
| resolve_lifetimes_for(tcx
, id
).defs
.get(&id
),
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
),
358 late_bound_vars_map
: |tcx
, id
| resolve_lifetimes_for(tcx
, id
).late_bound_vars
.get(&id
),
364 /// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
365 /// Also does not generate any diagnostics.
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.
375 /// The reason for this separate call is to resolve what would otherwise
376 /// be a cycle. Consider this example:
378 /// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub)
382 /// trait Sub<'b>: for<'a> Base<'a> {
383 /// type SubItem: Sub<BaseItem = &'b u32>;
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(
397 local_def_id
: LocalDefId
,
398 ) -> ResolveLifetimes
{
399 convert_named_region_map(do_resolve(tcx
, local_def_id
, true))
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))
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
{
420 map
: &mut named_region_map
,
422 trait_definition_only
,
423 xcrate_object_lifetime_defaults
: Default
::default(),
424 missing_named_lifetime_spots
: vec
![],
426 visitor
.visit_item(item
);
431 fn convert_named_region_map(named_region_map
: NamedRegionMap
) -> ResolveLifetimes
{
432 let mut rl
= ResolveLifetimes
::default();
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
);
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
);
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 }
);
462 hir
::ItemKind
::Trait(..) => tcx
.resolve_lifetimes_trait_definition(item_id
),
463 _
=> tcx
.resolve_lifetimes(item_id
),
466 tcx
.resolve_lifetimes(item_id
)
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
)) => {
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
);
482 let node
= parent_iter
.next().map(|n
| n
.1);
484 Some(hir
::Node
::Item(item
)) => break item
.def_id
,
485 Some(hir
::Node
::Crate(_
)) | None
=> bug
!("Called `item_for` on an Item."),
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(..))
500 fn late_region_as_bound_region
<'tcx
>(tcx
: TyCtxt
<'tcx
>, region
: &Region
) -> ty
::BoundVariableKind
{
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
))
506 Region
::LateBoundAnon(_
, _
, anon_idx
) => {
507 ty
::BoundVariableKind
::Region(ty
::BrAnon(*anon_idx
))
509 _
=> bug
!("{:?} is not a late region", region
),
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
![];
520 Scope
::Body { .. }
| Scope
::Root
=> {
521 break (vec
![], BinderScopeType
::Normal
);
524 Scope
::Elision { s, .. }
| Scope
::ObjectLifetimeDefault { s, .. }
=> {
528 Scope
::Supertrait { s, lifetimes }
=> {
529 supertrait_lifetimes
= lifetimes
.clone();
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
);
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
);
550 impl<'a
, 'tcx
> Visitor
<'tcx
> for LifetimeContext
<'a
, 'tcx
> {
551 type NestedFilter
= nested_filter
::All
;
553 fn nested_visit_map(&mut self) -> Self::Map
{
557 // We want to nest trait/impl items in their parent, but nothing else.
558 fn visit_nested_item(&mut self, _
: hir
::ItemId
) {}
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
)
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
);
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
<_
>) =
579 .filter(|param
| matches
!(param
.kind
, GenericParamKind
::Lifetime { .. }
))
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);
587 self.map
.late_bound_vars
.insert(e
.hir_id
, binders
);
588 let scope
= Scope
::Binder
{
593 opaque_type_parent
: false,
594 scope_type
: BinderScopeType
::Normal
,
595 allow_late_bound
: true,
596 where_bound_origin
: None
,
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
)
604 intravisit
::walk_expr(self, e
)
608 fn visit_item(&mut self, item
: &'tcx hir
::Item
<'tcx
>) {
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());
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
);
623 self.missing_named_lifetime_spots
.pop();
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
);
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
));
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.
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
))
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
);
662 for (&owner
, late_bound_vars
) in
663 resolved_lifetimes
.late_bound_vars
.iter()
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(),
674 hir
::Node
::Crate(_
) => bug
!("No Item about an OpaqueTy"),
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());
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
694 let mut non_lifetime_count
= 0;
695 let lifetimes
= generics
698 .filter_map(|param
| match param
.kind
{
699 GenericParamKind
::Lifetime { .. }
=> {
700 Some(Region
::early(self.tcx
.hir(), &mut index
, param
))
702 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
703 non_lifetime_count
+= 1;
708 self.map
.late_bound_vars
.insert(item
.hir_id(), vec
![]);
709 let scope
= Scope
::Binder
{
710 hir_id
: item
.hir_id(),
712 next_early_index
: index
+ non_lifetime_count
,
713 opaque_type_parent
: true,
714 scope_type
: BinderScopeType
::Normal
,
716 allow_late_bound
: false,
717 where_bound_origin
: None
,
719 self.with(scope
, |this
| {
720 let scope
= Scope
::TraitRefBoundary { s: this.scope }
;
721 this
.with(scope
, |this
| {
722 intravisit
::walk_item(this
, item
);
725 self.missing_named_lifetime_spots
.pop();
730 fn visit_foreign_item(&mut self, item
: &'tcx hir
::ForeignItem
<'tcx
>) {
732 hir
::ForeignItemKind
::Fn(_
, _
, ref generics
) => {
733 self.visit_early_late(None
, item
.hir_id(), generics
, |this
| {
734 intravisit
::walk_foreign_item(this
, item
);
737 hir
::ForeignItemKind
::Static(..) => {
738 intravisit
::walk_foreign_item(self, item
);
740 hir
::ForeignItemKind
::Type
=> {
741 intravisit
::walk_foreign_item(self, item
);
746 #[tracing::instrument(level = "debug", skip(self))]
747 fn visit_ty(&mut self, ty
: &'tcx hir
::Ty
<'tcx
>) {
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 }
=> {
758 let (span
, span_type
) = if let Some(span
) = lifetime_span
{
759 (span
.shrink_to_hi(), ForLifetimeSpanType
::TypeTail
)
761 (ty
.span
.shrink_to_lo(), ForLifetimeSpanType
::TypeEmpty
)
763 self.missing_named_lifetime_spots
764 .push(MissingLifetimeSpot
::HigherRanked { span, span_type }
);
765 let (lifetimes
, binders
): (FxIndexMap
<LocalDefId
, Region
>, Vec
<_
>) = c
768 .filter(|param
| matches
!(param
.kind
, GenericParamKind
::Lifetime { .. }
))
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);
776 self.map
.late_bound_vars
.insert(ty
.hir_id
, binders
);
777 let scope
= Scope
::Binder
{
782 opaque_type_parent
: false,
783 scope_type
: BinderScopeType
::Normal
,
784 allow_late_bound
: true,
785 where_bound_origin
: None
,
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
);
792 self.missing_named_lifetime_spots
.pop();
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
);
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",);
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
)
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`.
821 self.resolve_elided_lifetimes(&[lifetime
])
823 LifetimeName
::Param(..) | LifetimeName
::Static
=> {
824 // If the user wrote an explicit name, use that.
825 self.visit_lifetime(lifetime
);
827 LifetimeName
::Error
=> {}
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(),
836 self.with(scope
, |this
| this
.visit_ty(&mt
.ty
));
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
,
850 intravisit
::walk_ty(self, ty
);
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
);
864 hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy
{
865 origin
: hir
::OpaqueTyOrigin
::FnReturn(..) | hir
::OpaqueTyOrigin
::AsyncFn(..),
869 }) => (generics
, bounds
),
870 ref i
=> bug
!("`impl Trait` pointed to non-opaque type?? {:#?}", i
),
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 {
882 self.visit_lifetime(lifetime
);
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 {
892 let Some(def_id
) = def_id
.as_local() else {
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
{
904 "`impl Trait` can only capture lifetimes \
905 bound at the fn or impl level"
909 self.uninsert_lifetime_on_error(lifetime
, def
.unwrap());
911 if let hir
::Node
::Item(hir
::Item
{
912 kind
: hir
::ItemKind
::OpaqueTy { .. }
, ..
913 }) = self.tcx
.hir().get(parent_id
)
915 if !self.trait_definition_only
{
916 let mut err
= self.tcx
.sess
.struct_span_err(
918 "higher kinded lifetime bounds on nested opaque types are not supported yet",
920 err
.span_note(self.tcx
.def_span(def_id
), "lifetime declared here");
923 self.uninsert_lifetime_on_error(lifetime
, def
.unwrap());
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();
932 let mut elision
= None
;
933 let mut lifetimes
= FxIndexMap
::default();
934 let mut non_lifetime_count
= 0;
935 for param
in generics
.params
{
937 GenericParamKind
::Lifetime { .. }
=> {
938 let (def_id
, reg
) = Region
::early(self.tcx
.hir(), &mut index
, ¶m
);
939 if let hir
::ParamName
::Plain(Ident
{
940 name
: kw
::UnderscoreLifetime
,
944 // Pick the elided lifetime "definition" if one exists
945 // and use it to make an elision scope.
948 lifetimes
.insert(def_id
, reg
);
951 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
952 non_lifetime_count
+= 1;
956 let next_early_index
= index
+ non_lifetime_count
;
957 self.map
.late_bound_vars
.insert(ty
.hir_id
, vec
![]);
959 if let Some(elision_region
) = elision
{
961 Scope
::Elision { elide: Elide::Exact(elision_region), s: self.scope }
;
962 self.with(scope
, |this
| {
963 let scope
= Scope
::Binder
{
968 opaque_type_parent
: false,
969 scope_type
: BinderScopeType
::Normal
,
970 allow_late_bound
: false,
971 where_bound_origin
: None
,
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
);
984 let scope
= Scope
::Binder
{
989 opaque_type_parent
: false,
990 scope_type
: BinderScopeType
::Normal
,
991 allow_late_bound
: false,
992 where_bound_origin
: None
,
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
);
1005 _
=> intravisit
::walk_ty(self, ty
),
1009 fn visit_trait_item(&mut self, trait_item
: &'tcx hir
::TraitItem
<'tcx
>) {
1010 use self::hir
::TraitItemKind
::*;
1011 match trait_item
.kind
{
1013 self.missing_named_lifetime_spots
.push((&trait_item
.generics
).into());
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
),
1021 self.missing_named_lifetime_spots
.pop();
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
1032 .filter_map(|param
| match param
.kind
{
1033 GenericParamKind
::Lifetime { .. }
=> {
1034 Some(Region
::early(self.tcx
.hir(), &mut index
, param
))
1036 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
1037 non_lifetime_count
+= 1;
1042 self.map
.late_bound_vars
.insert(trait_item
.hir_id(), vec
![]);
1043 let scope
= Scope
::Binder
{
1044 hir_id
: trait_item
.hir_id(),
1046 next_early_index
: index
+ non_lifetime_count
,
1048 opaque_type_parent
: true,
1049 scope_type
: BinderScopeType
::Normal
,
1050 allow_late_bound
: false,
1051 where_bound_origin
: None
,
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
);
1060 if let Some(ty
) = ty
{
1065 self.missing_named_lifetime_spots
.pop();
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();
1077 fn visit_impl_item(&mut self, impl_item
: &'tcx hir
::ImplItem
<'tcx
>) {
1078 use self::hir
::ImplItemKind
::*;
1079 match impl_item
.kind
{
1081 self.missing_named_lifetime_spots
.push((&impl_item
.generics
).into());
1083 self.visit_early_late(
1084 Some(tcx
.hir().get_parent_item(impl_item
.hir_id())),
1086 &impl_item
.generics
,
1087 |this
| intravisit
::walk_impl_item(this
, impl_item
),
1089 self.missing_named_lifetime_spots
.pop();
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
1100 .filter_map(|param
| match param
.kind
{
1101 GenericParamKind
::Lifetime { .. }
=> {
1102 Some(Region
::early(self.tcx
.hir(), &mut index
, param
))
1104 GenericParamKind
::Const { .. }
| GenericParamKind
::Type { .. }
=> {
1105 non_lifetime_count
+= 1;
1110 self.map
.late_bound_vars
.insert(ty
.hir_id
, vec
![]);
1111 let scope
= Scope
::Binder
{
1114 next_early_index
: index
+ non_lifetime_count
,
1116 opaque_type_parent
: true,
1117 scope_type
: BinderScopeType
::Normal
,
1118 allow_late_bound
: true,
1119 where_bound_origin
: None
,
1121 self.with(scope
, |this
| {
1122 let scope
= Scope
::TraitRefBoundary { s: this.scope }
;
1123 this
.with(scope
, |this
| {
1124 this
.visit_generics(generics
);
1128 self.missing_named_lifetime_spots
.pop();
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();
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
)
1150 // If we've already reported an error, just ignore `lifetime_ref`.
1151 hir
::LifetimeName
::Error
=> {}
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
);
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
),
1169 self.visit_fn_like_elision(&fd
.inputs
, output
);
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
{
1177 GenericParamKind
::Lifetime { .. }
=> {}
1178 GenericParamKind
::Type { ref default, .. }
=> {
1179 if let Some(ref ty
) = default {
1183 GenericParamKind
::Const { ref ty, default }
=> {
1185 if let Some(default) = default {
1186 this
.visit_body(this
.tcx
.hir().body(default.body
));
1191 for predicate
in generics
.predicates
{
1193 &hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{
1196 ref bound_generic_params
,
1200 let (lifetimes
, binders
): (FxIndexMap
<LocalDefId
, Region
>, Vec
<_
>) =
1201 bound_generic_params
1204 matches
!(param
.kind
, GenericParamKind
::Lifetime { .. }
)
1207 .map(|(late_bound_idx
, param
)| {
1209 Region
::late(late_bound_idx
as u32, this
.tcx
.hir(), param
);
1210 let r
= late_region_as_bound_region(this
.tcx
, &pair
.1);
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
1220 let scope
= Scope
::Binder
{
1221 hir_id
: bounded_ty
.hir_id
,
1225 opaque_type_parent
: false,
1226 scope_type
: BinderScopeType
::Normal
,
1227 allow_late_bound
: true,
1228 where_bound_origin
: Some(origin
),
1230 this
.with(scope
, |this
| {
1231 this
.visit_ty(&bounded_ty
);
1232 walk_list
!(this
, visit_param_bound
, bounds
);
1235 &hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{
1240 this
.visit_lifetime(lifetime
);
1241 walk_list
!(this
, visit_param_bound
, bounds
);
1243 if lifetime
.name
!= hir
::LifetimeName
::Static
{
1244 for bound
in bounds
{
1245 let hir
::GenericBound
::Outlives(ref lt
) = bound
else {
1248 if lt
.name
!= hir
::LifetimeName
::Static
{
1251 this
.insert_lifetime(lt
, Region
::Static
);
1257 "unnecessary lifetime parameter `{}`",
1258 lifetime
.name
.ident(),
1262 "you can use the `'static` lifetime directly, in place of `{}`",
1263 lifetime
.name
.ident(),
1269 &hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{
1274 this
.visit_ty(lhs_ty
);
1275 this
.visit_ty(rhs_ty
);
1282 fn visit_param_bound(&mut self, bound
: &'tcx hir
::GenericBound
<'tcx
>) {
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();
1292 self.map
.late_bound_vars
.insert(*hir_id
, binders
);
1293 let scope
= Scope
::Binder
{
1295 lifetimes
: FxIndexMap
::default(),
1297 next_early_index
: self.next_early_index(),
1298 opaque_type_parent
: false,
1300 allow_late_bound
: true,
1301 where_bound_origin
: None
,
1303 self.with(scope
, |this
| {
1304 intravisit
::walk_param_bound(this
, bound
);
1307 _
=> intravisit
::walk_param_bound(self, bound
),
1311 fn visit_poly_trait_ref(
1313 trait_ref
: &'tcx hir
::PolyTraitRef
<'tcx
>,
1314 _modifier
: hir
::TraitBoundModifier
,
1316 debug
!("visit_poly_trait_ref(trait_ref={:?})", trait_ref
);
1318 let should_pop_missing_lt
= self.is_trait_ref_fn_scope(trait_ref
);
1320 let next_early_index
= self.next_early_index();
1321 let (mut binders
, scope_type
) = self.poly_trait_ref_binder_info();
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
1328 .filter(|param
| matches
!(param
.kind
, GenericParamKind
::Lifetime { .. }
))
1330 .map(|(late_bound_idx
, param
)| {
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);
1337 binders
.extend(binders_iter
);
1340 self.map
.late_bound_vars
.insert(trait_ref
.trait_ref
.hir_ref_id
, binders
);
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
1346 let scope
= Scope
::Binder
{
1347 hir_id
: trait_ref
.trait_ref
.hir_ref_id
,
1351 opaque_type_parent
: false,
1353 allow_late_bound
: true,
1354 where_bound_origin
: None
,
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
);
1361 if should_pop_missing_lt
{
1362 self.missing_named_lifetime_spots
.pop();
1367 fn compute_object_lifetime_defaults
<'tcx
>(
1369 item
: &hir
::Item
<'_
>,
1370 ) -> Option
<&'tcx
[ObjectLifetimeDefault
]> {
1372 hir
::ItemKind
::Struct(_
, ref generics
)
1373 | hir
::ItemKind
::Union(_
, ref generics
)
1374 | hir
::ItemKind
::Enum(_
, ref generics
)
1375 | hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy
{
1377 origin
: hir
::OpaqueTyOrigin
::TyAlias
,
1380 | hir
::ItemKind
::TyAlias(_
, ref generics
)
1381 | hir
::ItemKind
::Trait(_
, _
, ref generics
, ..) => {
1382 let result
= object_lifetime_defaults_for_item(tcx
, generics
);
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
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
1395 .find_map(|param
| match param
.kind
{
1396 GenericParamKind
::Lifetime { .. }
=> {
1398 return Some(param
.name
.ident().to_string().into());
1406 Set1
::One(_
) => bug
!(),
1407 Set1
::Many
=> "Ambiguous".into(),
1409 .collect
::<Vec
<Cow
<'
static, str>>>()
1411 tcx
.sess
.span_err(item
.span
, &object_lifetime_default_reprs
);
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
>(
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());
1435 let process_param
= |param
: &hir
::GenericParam
<'_
>| match param
.kind
{
1436 GenericParamKind
::Lifetime { .. }
=> None
,
1437 GenericParamKind
::Type { .. }
=> {
1438 let mut set
= Set1
::Empty
;
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 }
;
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() {
1451 let res
= match data
.bounded_ty
.kind
{
1452 hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) => path
.res
,
1456 if res
== Res
::Def(DefKind
::TyParam
, param_def_id
.to_def_id()) {
1457 add_bounds(&mut set
, &data
.bounds
);
1462 Set1
::Empty
=> Set1
::Empty
,
1463 Set1
::One(name
) => {
1464 if name
== hir
::LifetimeName
::Static
{
1465 Set1
::One(Region
::Static
)
1470 .filter_map(|param
| match param
.kind
{
1471 GenericParamKind
::Lifetime { .. }
=> {
1472 let param_def_id
= tcx
.hir().local_def_id(param
.hir_id
);
1475 hir
::LifetimeName
::Param(param_def_id
, param
.name
),
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()))
1487 Set1
::Many
=> Set1
::Many
,
1490 GenericParamKind
::Const { .. }
=> {
1491 // Generic consts don't impose any constraints.
1493 // We still store a dummy value here to allow generic parameters
1494 // in an arbitrary order.
1499 tcx
.arena
.alloc_from_iter(generics
.params
.iter().filter_map(process_param
))
1502 impl<'a
, 'tcx
> LifetimeContext
<'a
, 'tcx
> {
1503 fn with
<F
>(&mut self, wrap_scope
: Scope
<'_
>, f
: F
)
1505 F
: for<'b
> FnOnce(&mut LifetimeContext
<'b
, 'tcx
>),
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
{
1514 trait_definition_only
: self.trait_definition_only
,
1515 xcrate_object_lifetime_defaults
,
1516 missing_named_lifetime_spots
,
1518 let span
= tracing
::debug_span
!("scope", scope
= ?
TruncatedScopeDebug(&this
.scope
));
1520 let _enter
= span
.enter();
1523 self.xcrate_object_lifetime_defaults
= this
.xcrate_object_lifetime_defaults
;
1524 self.missing_named_lifetime_spots
= this
.missing_named_lifetime_spots
;
1527 /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
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.
1535 /// fn foo<'a,'b,'c,T:Trait<'b>>(...)
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.
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
>(
1547 parent_id
: Option
<LocalDefId
>,
1549 generics
: &'tcx hir
::Generics
<'tcx
>,
1552 F
: for<'b
, 'c
> FnOnce(&'b
mut LifetimeContext
<'c
, 'tcx
>),
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
1562 hir
::ItemKind
::Trait(_
, _
, ref generics
, ..)
1563 | hir
::ItemKind
::Impl(hir
::Impl { ref generics, .. }
) => {
1564 next_early_index
+= generics
.params
.len() as u32;
1570 let mut non_lifetime_count
= 0;
1571 let mut named_late_bound_vars
= 0;
1572 let lifetimes
: FxIndexMap
<LocalDefId
, Region
> = generics
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
))
1582 Some(Region
::early(self.tcx
.hir(), &mut next_early_index
, param
))
1585 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
1586 non_lifetime_count
+= 1;
1591 let next_early_index
= next_early_index
+ non_lifetime_count
;
1593 let binders
: Vec
<_
> = generics
1597 matches
!(param
.kind
, GenericParamKind
::Lifetime { .. }
)
1598 && self.tcx
.is_late_bound(param
.hir_id
)
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)
1606 self.map
.late_bound_vars
.insert(hir_id
, binders
);
1607 let scope
= Scope
::Binder
{
1612 opaque_type_parent
: true,
1613 scope_type
: BinderScopeType
::Normal
,
1614 allow_late_bound
: true,
1615 where_bound_origin
: None
,
1617 self.with(scope
, walk
);
1620 fn next_early_index_helper(&self, only_opaque_type_parent
: bool
) -> u32 {
1621 let mut scope
= self.scope
;
1624 Scope
::Root
=> return 0,
1626 Scope
::Binder { next_early_index, opaque_type_parent, .. }
1627 if (!only_opaque_type_parent
|| opaque_type_parent
) =>
1629 return next_early_index
;
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
,
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)
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)
1656 #[tracing::instrument(level = "debug", skip(self))]
1657 fn resolve_lifetime_ref(
1659 region_def_id
: LocalDefId
,
1660 lifetime_ref
: &'tcx hir
::Lifetime
,
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.
1666 let mut late_depth
= 0;
1667 let mut scope
= self.scope
;
1668 let mut outermost_body
= None
;
1671 Scope
::Body { id, s }
=> {
1672 outermost_body
= Some(id
);
1680 Scope
::Binder { ref lifetimes, scope_type, s, .. }
=> {
1681 if let Some(&def
) = lifetimes
.get(®ion_def_id
) {
1682 break Some(def
.shifted(late_depth
));
1685 BinderScopeType
::Normal
=> late_depth
+= 1,
1686 BinderScopeType
::Concatenating
=> {}
1691 Scope
::Elision { s, .. }
1692 | Scope
::ObjectLifetimeDefault { s, .. }
1693 | Scope
::Supertrait { s, .. }
1694 | Scope
::TraitRefBoundary { s, .. }
=> {
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(..), ..
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());
1718 self.insert_lifetime(lifetime_ref
, def
);
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.
1727 // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1730 // In such case, walk back the binders to diagnose it properly.
1731 let mut scope
= self.scope
;
1735 where_bound_origin
: Some(hir
::PredicateOrigin
::ImplTrait
), ..
1737 let mut err
= self.tcx
.sess
.struct_span_err(
1739 "`impl Trait` can only mention lifetimes bound at the fn or impl level",
1741 err
.span_note(self.tcx
.def_span(region_def_id
), "lifetime declared here");
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, .. }
=> {
1757 self.tcx
.sess
.delay_span_bug(
1759 &format
!("Could not resolve {:?} in scope {:#?}", lifetime_ref
, self.scope
,),
1763 fn visit_segment_args(
1767 generic_args
: &'tcx hir
::GenericArgs
<'tcx
>,
1770 "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})",
1771 res
, depth
, generic_args
,
1774 if generic_args
.parenthesized
{
1775 self.visit_fn_like_elision(generic_args
.inputs(), Some(generic_args
.bindings
[0].ty()));
1779 let mut elide_lifetimes
= true;
1780 let lifetimes
: Vec
<_
> = generic_args
1783 .filter_map(|arg
| match arg
{
1784 hir
::GenericArg
::Lifetime(lt
) => {
1785 if !lt
.is_elided() {
1786 elide_lifetimes
= false;
1793 // We short-circuit here if all are elided in order to pluralize
1795 if elide_lifetimes
{
1796 self.resolve_elided_lifetimes(&lifetimes
);
1798 lifetimes
.iter().for_each(|lt
| self.visit_lifetime(lt
));
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") }
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
)),
1817 ) if depth
== 0 => Some(def_id
),
1821 debug
!("visit_segment_args: type_def_id={:?}", type_def_id
);
1823 // Compute a vector of defaults, one for each type parameter,
1824 // per the rules given in RFCs 599 and 1156. Example:
1827 // struct Foo<'a, T: 'a, U> { }
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
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
| {
1840 let mut scope
= self.scope
;
1843 Scope
::Root
=> break false,
1845 Scope
::Body { .. }
=> break true,
1847 Scope
::Binder { s, .. }
1848 | Scope
::Elision { s, .. }
1849 | Scope
::ObjectLifetimeDefault { s, .. }
1850 | Scope
::Supertrait { s, .. }
1851 | Scope
::TraitRefBoundary { s, .. }
=> {
1858 let map
= &self.map
;
1859 let set_to_region
= |set
: &ObjectLifetimeDefault
| match *set
{
1864 Some(Region
::Static
)
1868 let lifetimes
= generic_args
.args
.iter().filter_map(|arg
| match arg
{
1869 GenericArg
::Lifetime(lt
) => Some(lt
),
1872 r
.subst(lifetimes
, map
)
1876 if let Some(def_id
) = def_id
.as_local() {
1877 let id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
);
1879 .object_lifetime_defaults(id
.owner
)
1886 self.xcrate_object_lifetime_defaults
1888 .or_insert_with(|| {
1889 tcx
.generics_of(def_id
)
1892 .filter_map(|param
| match param
.kind
{
1893 GenericParamDefKind
::Type { object_lifetime_default, .. }
=> {
1894 Some(object_lifetime_default
)
1896 GenericParamDefKind
::Const { .. }
=> Some(Set1
::Empty
),
1897 GenericParamDefKind
::Lifetime
=> None
,
1907 debug
!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults
);
1910 for arg
in generic_args
.args
{
1912 GenericArg
::Lifetime(_
) => {}
1913 GenericArg
::Type(ty
) => {
1914 if let Some(<
) = object_lifetime_defaults
.get(i
) {
1915 let scope
= Scope
::ObjectLifetimeDefault { lifetime: lt, s: self.scope }
;
1916 self.with(scope
, |this
| this
.visit_ty(ty
));
1922 GenericArg
::Const(ct
) => {
1923 self.visit_anon_const(&ct
.value
);
1926 GenericArg
::Infer(inf
) => {
1927 self.visit_id(inf
.hir_id
);
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`:
1946 // but if we just have `type Item;`, then it would be
1947 // `'static`. However, we don't get all of this logic correct.
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.
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(_
)));
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) }
,
1967 if let Some(type_def_id
) = type_def_id
{
1968 let lifetimes
= LifetimeContext
::supertrait_hrtb_lifetimes(
1973 self.with(scope
, |this
| {
1974 let scope
= Scope
::Supertrait
{
1975 lifetimes
: lifetimes
.unwrap_or_default(),
1978 this
.with(scope
, |this
| this
.visit_assoc_type_binding(binding
));
1981 self.with(scope
, |this
| this
.visit_assoc_type_binding(binding
));
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> {
1993 /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
1994 /// trait Bar: for<'b> Bar<'b> {}
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(
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
)
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();
2014 let Some((def_id
, bound_vars
)) = stack
.pop() else {
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
=> {}
2024 if trait_defines_associated_type_named(def_id
) {
2025 break Some(bound_vars
.into_iter().collect());
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
))
2044 let obligations
= obligations
.filter(|o
| visited
.insert(o
.0));
2045 stack
.extend(obligations
);
2049 #[tracing::instrument(level = "debug", skip(self))]
2050 fn visit_fn_like_elision(
2052 inputs
: &'tcx
[hir
::Ty
<'tcx
>],
2053 output
: Option
<&'tcx hir
::Ty
<'tcx
>>,
2055 debug
!("visit_fn_like_elision: enter");
2056 let mut scope
= &*self.scope
;
2059 Scope
::Binder { hir_id, allow_late_bound: true, .. }
=> {
2062 Scope
::ObjectLifetimeDefault { ref s, .. }
2063 | Scope
::Elision { ref s, .. }
2064 | Scope
::Supertrait { ref s, .. }
2065 | Scope
::TraitRefBoundary { ref s, .. }
=> {
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",
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
);
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
))),
2093 let arg_scope
= Scope
::Elision
{
2094 elide
: Elide
::FreshLateAnon(named_late_bound_vars
, Cell
::new(0)),
2097 self.with(arg_scope
, |this
| {
2098 for input
in inputs
{
2099 this
.visit_ty(input
);
2103 let Some(output
) = output
else { return }
;
2105 debug
!("determine output");
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
),
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
2121 trait_items
.iter().find(|ti
| ti
.id
.hir_id() == parent
).map(|ti
| ti
.kind
);
2124 hir
::TraitFn
::Required(_
) => None
,
2125 hir
::TraitFn
::Provided(body
) => Some(body
),
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
2133 impl_self
= Some(self_ty
);
2135 items
.iter().find(|ii
| ii
.id
.hir_id() == parent
).map(|ii
| ii
.kind
);
2140 // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
2141 Node
::ForeignItem(_
) | Node
::Ty(_
) | Node
::TraitRef(_
) => None
,
2143 Node
::TypeBinding(_
) if let Node
::TraitRef(_
) = self.tcx
.hir().get(self.tcx
.hir().get_parent_node(parent
)) => None
,
2145 // Everything else (only closures?) doesn't
2146 // actually enjoy elision in return types.
2148 self.visit_ty(output
);
2153 let has_self
= match assoc_item_kind
{
2154 Some(hir
::AssocItemKind
::Fn { has_self }
) => has_self
,
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.
2163 struct SelfVisitor
<'a
> {
2164 map
: &'a NamedRegionMap
,
2165 impl_self
: Option
<&'a hir
::TyKind
<'a
>>,
2166 lifetime
: Set1
<Region
>,
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
{
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
))) =
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
,
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
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
);
2208 intravisit
::walk_ty(self, ty
)
2212 let mut visitor
= SelfVisitor
{
2214 impl_self
: impl_self
.map(|ty
| &ty
.kind
),
2215 lifetime
: Set1
::Empty
,
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
));
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
2233 .skip(has_self
as usize)
2235 let mut gather
= GatherLifetimes
{
2237 outer_index
: ty
::INNERMOST
,
2238 have_bound_regions
: false,
2239 lifetimes
: Default
::default(),
2241 gather
.visit_ty(input
);
2243 lifetime_count
+= gather
.lifetimes
.len();
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();
2252 ElisionFailureInfo
{
2255 lifetime_count
: gather
.lifetimes
.len(),
2256 have_bound_regions
: gather
.have_bound_regions
,
2262 let elide
= if lifetime_count
== 1 {
2263 Elide
::Exact(possible_implied_output_region
.unwrap())
2265 Elide
::Error(arg_lifetimes
)
2270 let scope
= Scope
::Elision { elide, s: self.scope }
;
2271 self.with(scope
, |this
| this
.visit_ty(output
));
2273 struct GatherLifetimes
<'a
> {
2274 map
: &'a NamedRegionMap
,
2275 outer_index
: ty
::DebruijnIndex
,
2276 have_bound_regions
: bool
,
2277 lifetimes
: FxHashSet
<Region
>,
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);
2286 hir
::TyKind
::TraitObject(bounds
, ref lifetime
, _
) => {
2287 for bound
in bounds
{
2288 self.visit_poly_trait_ref(bound
, hir
::TraitBoundModifier
::None
);
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
);
2298 intravisit
::walk_ty(self, ty
);
2301 if let hir
::TyKind
::BareFn(_
) = ty
.kind
{
2302 self.outer_index
.shift_out(1);
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;
2313 intravisit
::walk_generic_param(self, param
);
2316 fn visit_poly_trait_ref(
2318 trait_ref
: &hir
::PolyTraitRef
<'_
>,
2319 modifier
: hir
::TraitBoundModifier
,
2321 self.outer_index
.shift_in(1);
2322 intravisit
::walk_poly_trait_ref(self, trait_ref
, modifier
);
2323 self.outer_index
.shift_out(1);
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);
2332 intravisit
::walk_param_bound(self, bound
);
2336 fn visit_lifetime(&mut self, lifetime_ref
: &hir
::Lifetime
) {
2337 if let Some(&lifetime
) = self.map
.defs
.get(&lifetime_ref
.hir_id
) {
2339 Region
::LateBound(debruijn
, _
, _
)
2340 | Region
::LateBoundAnon(debruijn
, _
, _
)
2341 if debruijn
< self.outer_index
=>
2343 self.have_bound_regions
= true;
2346 // FIXME(jackh726): nested trait refs?
2347 self.lifetimes
.insert(lifetime
.shifted_out_to_binder(self.outer_index
));
2354 struct GatherAnonLifetimes
{
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
{
2364 intravisit
::walk_ty(self, ty
);
2367 fn visit_generic_args(
2370 generic_args
: &'v hir
::GenericArgs
<'v
>,
2372 // parenthesized args enter a new elision scope
2373 if generic_args
.parenthesized
{
2376 intravisit
::walk_generic_args(self, path_span
, generic_args
)
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;
2388 fn resolve_elided_lifetimes(&mut self, lifetime_refs
: &[&'tcx hir
::Lifetime
]) {
2389 debug
!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs
);
2391 if lifetime_refs
.is_empty() {
2395 let mut late_depth
= 0;
2396 let mut scope
= self.scope
;
2397 let mut in_scope_lifetimes
= FxIndexSet
::default();
2400 // Do not assign any resolution, it will be inferred.
2401 Scope
::Body { .. }
=> return,
2403 Scope
::Root
=> break None
,
2405 Scope
::Binder { s, ref lifetimes, scope_type, .. }
=> {
2406 // collect named lifetimes for suggestions
2407 in_scope_lifetimes
.extend(lifetimes
.keys().copied());
2409 BinderScopeType
::Normal
=> late_depth
+= 1,
2410 BinderScopeType
::Concatenating
=> {}
2416 elide
: Elide
::FreshLateAnon(named_late_bound_vars
, ref counter
),
2419 for lifetime_ref
in lifetime_refs
{
2421 Region
::late_anon(named_late_bound_vars
, counter
).shifted(late_depth
);
2423 self.insert_lifetime(lifetime_ref
, lifetime
);
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
);
2436 Scope
::Elision { elide: Elide::Error(ref e), ref s, .. }
=> {
2440 Scope
::Binder { ref lifetimes, s, .. }
=> {
2441 // Collect named lifetimes for suggestions.
2442 in_scope_lifetimes
.extend(lifetimes
.keys().copied());
2445 Scope
::ObjectLifetimeDefault { ref s, .. }
2446 | Scope
::Elision { ref s, .. }
2447 | Scope
::TraitRefBoundary { ref s, .. }
=> {
2456 Scope
::Elision { elide: Elide::Forbid, .. }
=> break None
,
2458 Scope
::ObjectLifetimeDefault { s, .. }
2459 | Scope
::Supertrait { s, .. }
2460 | Scope
::TraitRefBoundary { s, .. }
=> {
2466 let mut spans
: Vec
<_
> = lifetime_refs
.iter().map(|lt
| lt
.span
).collect();
2468 let mut spans_dedup
= spans
.clone();
2469 spans_dedup
.dedup();
2470 let spans_with_counts
: Vec
<_
> = spans_dedup
2472 .map(|sp
| (sp
, spans
.iter().filter(|nsp
| *nsp
== &sp
).count()))
2475 let mut err
= self.report_missing_lifetime_specifiers(spans
.clone(), lifetime_refs
.len());
2477 self.add_missing_lifetime_specifiers_label(
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 {
2492 Scope
::Binder { s, scope_type, .. }
=> {
2494 BinderScopeType
::Normal
=> late_depth
+= 1,
2495 BinderScopeType
::Concatenating
=> {}
2500 Scope
::Root
| Scope
::Elision { .. }
=> break Region
::Static
,
2502 Scope
::Body { .. }
| Scope
::ObjectLifetimeDefault { lifetime: None, .. }
=> return,
2504 Scope
::ObjectLifetimeDefault { lifetime: Some(l), .. }
=> break l
,
2506 Scope
::Supertrait { s, .. }
| Scope
::TraitRefBoundary { s, .. }
=> {
2511 self.insert_lifetime(lifetime_ref
, lifetime
.shifted(late_depth
));
2514 #[tracing::instrument(level = "debug", skip(self))]
2515 fn insert_lifetime(&mut self, lifetime_ref
: &'tcx hir
::Lifetime
, def
: Region
) {
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
)
2520 self.map
.defs
.insert(lifetime_ref
.hir_id
, def
);
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
));
2532 /// Detects late-bound lifetimes and inserts them into
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.
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
)?
;
2547 let mut late_bound
= FxIndexSet
::default();
2549 let mut constrained_by_input
= ConstrainedCollector
::default();
2550 for arg_ty
in decl
.inputs
{
2551 constrained_by_input
.visit_ty(arg_ty
);
2554 let mut appears_in_output
= AllCollector
::default();
2555 intravisit
::walk_fn_ret_ty(&mut appears_in_output
, &decl
.output
);
2557 debug
!(?constrained_by_input
.regions
);
2559 // Walk the lifetimes that appear in where clauses.
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
);
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
{
2573 hir
::GenericParamKind
::Lifetime { .. }
=> { /* fall through */ }
2575 // Neither types nor consts are late-bound.
2576 hir
::GenericParamKind
::Type { .. }
| hir
::GenericParamKind
::Const { .. }
=> continue,
2579 let param_def_id
= tcx
.hir().local_def_id(param
.hir_id
);
2581 // appears in the where clauses? early-bound.
2582 if appears_in_where_clause
.regions
.contains(¶m_def_id
) {
2586 // does not appear in the inputs, but appears in the return type? early-bound.
2587 if !constrained_by_input
.regions
.contains(¶m_def_id
)
2588 && appears_in_output
.regions
.contains(¶m_def_id
)
2593 debug
!("lifetime {:?} with id {:?} is late-bound", param
.name
.ident(), param
.hir_id
);
2595 let inserted
= late_bound
.insert(param_def_id
);
2596 assert
!(inserted
, "visited lifetime {:?} twice", param
.hir_id
);
2599 debug
!(?late_bound
);
2600 return Some(tcx
.arena
.alloc(late_bound
));
2603 struct ConstrainedCollector
{
2604 regions
: FxHashSet
<LocalDefId
>,
2607 impl<'v
> Visitor
<'v
> for ConstrainedCollector
{
2608 fn visit_ty(&mut self, ty
: &'v hir
::Ty
<'v
>) {
2611 hir
::QPath
::Resolved(Some(_
), _
) | hir
::QPath
::TypeRelative(..),
2613 // ignore lifetimes appearing in associated type
2614 // projections, as they are not *constrained*
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
2624 if let Some(last_segment
) = path
.segments
.last() {
2625 self.visit_path_segment(path
.span
, last_segment
);
2630 intravisit
::walk_ty(self, ty
);
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
);
2643 struct AllCollector
{
2644 regions
: FxHashSet
<LocalDefId
>,
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
);