1 //! Name resolution for lifetimes.
3 //! Name resolution for lifetimes follows *much* simpler rules than the
4 //! full resolve. For example, lifetime names are never exported or
5 //! used between functions, and they operate in a purely top-down
6 //! way. Therefore, we break lifetime name resolution into a separate pass.
8 use crate::late
::diagnostics
::{ForLifetimeSpanType, MissingLifetimeSpot}
;
11 use rustc_ast
::walk_list
;
12 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
13 use rustc_errors
::{struct_span_err, Applicability, DiagnosticBuilder}
;
15 use rustc_hir
::def
::{DefKind, Res}
;
16 use rustc_hir
::def_id
::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}
;
17 use rustc_hir
::intravisit
::{self, NestedVisitorMap, Visitor}
;
18 use rustc_hir
::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}
;
19 use rustc_hir
::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind}
;
20 use rustc_middle
::hir
::map
::Map
;
21 use rustc_middle
::middle
::resolve_lifetime
::*;
22 use rustc_middle
::ty
::{self, DefIdTree, GenericParamDefKind, TyCtxt}
;
23 use rustc_middle
::{bug, span_bug}
;
24 use rustc_session
::lint
;
25 use rustc_span
::symbol
::{kw, sym}
;
29 use std
::mem
::{replace, take}
;
33 // This counts the no of times a lifetime is used
34 #[derive(Clone, Copy, Debug)]
35 pub enum LifetimeUseSet
<'tcx
> {
36 One(&'tcx hir
::Lifetime
),
41 fn early(hir_map
: &Map
<'_
>, index
: &mut u32, param
: &GenericParam
<'_
>) -> (ParamName
, Region
);
43 fn late(hir_map
: &Map
<'_
>, param
: &GenericParam
<'_
>) -> (ParamName
, Region
);
45 fn late_anon(index
: &Cell
<u32>) -> Region
;
47 fn id(&self) -> Option
<DefId
>;
49 fn shifted(self, amount
: u32) -> Region
;
51 fn shifted_out_to_binder(self, binder
: ty
::DebruijnIndex
) -> Region
;
53 fn subst
<'a
, L
>(self, params
: L
, map
: &NamedRegionMap
) -> Option
<Region
>
55 L
: Iterator
<Item
= &'a hir
::Lifetime
>;
58 impl RegionExt
for Region
{
59 fn early(hir_map
: &Map
<'_
>, index
: &mut u32, param
: &GenericParam
<'_
>) -> (ParamName
, Region
) {
62 let def_id
= hir_map
.local_def_id(param
.hir_id
);
63 let origin
= LifetimeDefOrigin
::from_param(param
);
64 debug
!("Region::early: index={} def_id={:?}", i
, def_id
);
65 (param
.name
.normalize_to_macros_2_0(), Region
::EarlyBound(i
, def_id
, origin
))
68 fn late(hir_map
: &Map
<'_
>, param
: &GenericParam
<'_
>) -> (ParamName
, Region
) {
69 let depth
= ty
::INNERMOST
;
70 let def_id
= hir_map
.local_def_id(param
.hir_id
);
71 let origin
= LifetimeDefOrigin
::from_param(param
);
73 "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}",
74 param
, depth
, def_id
, origin
,
76 (param
.name
.normalize_to_macros_2_0(), Region
::LateBound(depth
, def_id
, origin
))
79 fn late_anon(index
: &Cell
<u32>) -> Region
{
82 let depth
= ty
::INNERMOST
;
83 Region
::LateBoundAnon(depth
, i
)
86 fn id(&self) -> Option
<DefId
> {
88 Region
::Static
| Region
::LateBoundAnon(..) => None
,
90 Region
::EarlyBound(_
, id
, _
) | Region
::LateBound(_
, id
, _
) | Region
::Free(_
, id
) => {
96 fn shifted(self, amount
: u32) -> Region
{
98 Region
::LateBound(debruijn
, id
, origin
) => {
99 Region
::LateBound(debruijn
.shifted_in(amount
), id
, origin
)
101 Region
::LateBoundAnon(debruijn
, index
) => {
102 Region
::LateBoundAnon(debruijn
.shifted_in(amount
), index
)
108 fn shifted_out_to_binder(self, binder
: ty
::DebruijnIndex
) -> Region
{
110 Region
::LateBound(debruijn
, id
, origin
) => {
111 Region
::LateBound(debruijn
.shifted_out_to_binder(binder
), id
, origin
)
113 Region
::LateBoundAnon(debruijn
, index
) => {
114 Region
::LateBoundAnon(debruijn
.shifted_out_to_binder(binder
), index
)
120 fn subst
<'a
, L
>(self, mut params
: L
, map
: &NamedRegionMap
) -> Option
<Region
>
122 L
: Iterator
<Item
= &'a hir
::Lifetime
>,
124 if let Region
::EarlyBound(index
, _
, _
) = self {
125 params
.nth(index
as usize).and_then(|lifetime
| map
.defs
.get(&lifetime
.hir_id
).cloned())
132 /// Maps the id of each lifetime reference to the lifetime decl
133 /// that it corresponds to.
135 /// FIXME. This struct gets converted to a `ResolveLifetimes` for
136 /// actual use. It has the same data, but indexed by `LocalDefId`. This
139 struct NamedRegionMap
{
140 // maps from every use of a named (not anonymous) lifetime to a
141 // `Region` describing how that region is bound
142 defs
: HirIdMap
<Region
>,
144 // the set of lifetime def ids that are late-bound; a region can
145 // be late-bound if (a) it does NOT appear in a where-clause and
146 // (b) it DOES appear in the arguments.
147 late_bound
: HirIdSet
,
149 // For each type and trait definition, maps type parameters
150 // to the trait object lifetime defaults computed from them.
151 object_lifetime_defaults
: HirIdMap
<Vec
<ObjectLifetimeDefault
>>,
154 crate struct LifetimeContext
<'a
, 'tcx
> {
155 crate tcx
: TyCtxt
<'tcx
>,
156 map
: &'a
mut NamedRegionMap
,
159 /// This is slightly complicated. Our representation for poly-trait-refs contains a single
160 /// binder and thus we only allow a single level of quantification. However,
161 /// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>`
162 /// and `for <'a, 'b> &'b T: Foo<'a>`. In order to get the De Bruijn indices
163 /// correct when representing these constraints, we should only introduce one
164 /// scope. However, we want to support both locations for the quantifier and
165 /// during lifetime resolution we want precise information (so we can't
166 /// desugar in an earlier phase).
168 /// So, if we encounter a quantifier at the outer scope, we set
169 /// `trait_ref_hack` to `true` (and introduce a scope), and then if we encounter
170 /// a quantifier at the inner scope, we error. If `trait_ref_hack` is `false`,
171 /// then we introduce the scope at the inner quantifier.
172 trait_ref_hack
: bool
,
174 /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
175 is_in_fn_syntax
: bool
,
177 /// List of labels in the function/method currently under analysis.
178 labels_in_fn
: Vec
<ast
::Ident
>,
180 /// Cache for cross-crate per-definition object lifetime defaults.
181 xcrate_object_lifetime_defaults
: DefIdMap
<Vec
<ObjectLifetimeDefault
>>,
183 lifetime_uses
: &'a
mut DefIdMap
<LifetimeUseSet
<'tcx
>>,
185 /// When encountering an undefined named lifetime, we will suggest introducing it in these
187 crate missing_named_lifetime_spots
: Vec
<MissingLifetimeSpot
<'tcx
>>,
192 /// Declares lifetimes, and each can be early-bound or late-bound.
193 /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
194 /// it should be shifted by the number of `Binder`s in between the
195 /// declaration `Binder` and the location it's referenced from.
197 lifetimes
: FxHashMap
<hir
::ParamName
, Region
>,
199 /// if we extend this scope with another scope, what is the next index
200 /// we should use for an early-bound region?
201 next_early_index
: u32,
203 /// Flag is set to true if, in this binder, `'_` would be
204 /// equivalent to a "single-use region". This is true on
205 /// impls, but not other kinds of items.
206 track_lifetime_uses
: bool
,
208 /// Whether or not this binder would serve as the parent
209 /// binder for opaque types introduced within. For example:
212 /// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
215 /// Here, the opaque types we create for the `impl Trait`
216 /// and `impl Trait2` references will both have the `foo` item
217 /// as their parent. When we get to `impl Trait2`, we find
218 /// that it is nested within the `for<>` binder -- this flag
219 /// allows us to skip that when looking for the parent binder
220 /// of the resulting opaque type.
221 opaque_type_parent
: bool
,
226 /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
227 /// if this is a fn body, otherwise the original definitions are used.
228 /// Unspecified lifetimes are inferred, unless an elision scope is nested,
229 /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
235 /// A scope which either determines unspecified lifetimes or errors
236 /// on them (e.g., due to ambiguity). For more details, see `Elide`.
242 /// Use a specific lifetime (if `Some`) or leave it unset (to be
243 /// inferred in a function body or potentially error outside one),
244 /// for the default choice of lifetime in a trait object type.
245 ObjectLifetimeDefault
{
246 lifetime
: Option
<Region
>,
253 #[derive(Clone, Debug)]
255 /// Use a fresh anonymous late-bound lifetime each time, by
256 /// incrementing the counter to generate sequential indices.
257 FreshLateAnon(Cell
<u32>),
258 /// Always use this one lifetime.
260 /// Less or more than one lifetime were found, error on unspecified.
261 Error(Vec
<ElisionFailureInfo
>),
264 #[derive(Clone, Debug)]
265 crate struct ElisionFailureInfo
{
266 /// Where we can find the argument pattern.
267 parent
: Option
<hir
::BodyId
>,
268 /// The index of the argument in the original definition.
270 lifetime_count
: usize,
271 have_bound_regions
: bool
,
275 type ScopeRef
<'a
> = &'a Scope
<'a
>;
277 const ROOT_SCOPE
: ScopeRef
<'
static> = &Scope
::Root
;
279 pub fn provide(providers
: &mut ty
::query
::Providers
<'_
>) {
280 *providers
= ty
::query
::Providers
{
283 named_region_map
: |tcx
, id
| tcx
.resolve_lifetimes(LOCAL_CRATE
).defs
.get(&id
),
284 is_late_bound_map
: |tcx
, id
| tcx
.resolve_lifetimes(LOCAL_CRATE
).late_bound
.get(&id
),
285 object_lifetime_defaults_map
: |tcx
, id
| {
286 tcx
.resolve_lifetimes(LOCAL_CRATE
).object_lifetime_defaults
.get(&id
)
293 /// Computes the `ResolveLifetimes` map that contains data for the
294 /// entire crate. You should not read the result of this query
295 /// directly, but rather use `named_region_map`, `is_late_bound_map`,
297 fn resolve_lifetimes(tcx
: TyCtxt
<'_
>, for_krate
: CrateNum
) -> &ResolveLifetimes
{
298 assert_eq
!(for_krate
, LOCAL_CRATE
);
300 let named_region_map
= krate(tcx
);
302 let mut rl
= ResolveLifetimes
::default();
304 for (hir_id
, v
) in named_region_map
.defs
{
305 let map
= rl
.defs
.entry(hir_id
.owner
).or_default();
306 map
.insert(hir_id
.local_id
, v
);
308 for hir_id
in named_region_map
.late_bound
{
309 let map
= rl
.late_bound
.entry(hir_id
.owner
).or_default();
310 map
.insert(hir_id
.local_id
);
312 for (hir_id
, v
) in named_region_map
.object_lifetime_defaults
{
313 let map
= rl
.object_lifetime_defaults
.entry(hir_id
.owner
).or_default();
314 map
.insert(hir_id
.local_id
, v
);
320 fn krate(tcx
: TyCtxt
<'_
>) -> NamedRegionMap
{
321 let krate
= tcx
.hir().krate();
322 let mut map
= NamedRegionMap
{
323 defs
: Default
::default(),
324 late_bound
: Default
::default(),
325 object_lifetime_defaults
: compute_object_lifetime_defaults(tcx
),
328 let mut visitor
= LifetimeContext
{
332 trait_ref_hack
: false,
333 is_in_fn_syntax
: false,
334 labels_in_fn
: vec
![],
335 xcrate_object_lifetime_defaults
: Default
::default(),
336 lifetime_uses
: &mut Default
::default(),
337 missing_named_lifetime_spots
: vec
![],
339 for item
in krate
.items
.values() {
340 visitor
.visit_item(item
);
346 /// In traits, there is an implicit `Self` type parameter which comes before the generics.
347 /// We have to account for this when computing the index of the other generic parameters.
348 /// This function returns whether there is such an implicit parameter defined on the given item.
349 fn sub_items_have_self_param(node
: &hir
::ItemKind
<'_
>) -> bool
{
351 hir
::ItemKind
::Trait(..) | hir
::ItemKind
::TraitAlias(..) => true,
356 impl<'a
, 'tcx
> Visitor
<'tcx
> for LifetimeContext
<'a
, 'tcx
> {
357 type Map
= Map
<'tcx
>;
359 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
360 NestedVisitorMap
::All(self.tcx
.hir())
363 // We want to nest trait/impl items in their parent, but nothing else.
364 fn visit_nested_item(&mut self, _
: hir
::ItemId
) {}
366 fn visit_nested_body(&mut self, body
: hir
::BodyId
) {
367 // Each body has their own set of labels, save labels.
368 let saved
= take(&mut self.labels_in_fn
);
369 let body
= self.tcx
.hir().body(body
);
370 extract_labels(self, body
);
371 self.with(Scope
::Body { id: body.id(), s: self.scope }
, |_
, this
| {
372 this
.visit_body(body
);
374 replace(&mut self.labels_in_fn
, saved
);
377 fn visit_item(&mut self, item
: &'tcx hir
::Item
<'tcx
>) {
379 hir
::ItemKind
::Fn(ref sig
, ref generics
, _
) => {
380 self.missing_named_lifetime_spots
.push(generics
.into());
381 self.visit_early_late(None
, &sig
.decl
, generics
, |this
| {
382 intravisit
::walk_item(this
, item
);
384 self.missing_named_lifetime_spots
.pop();
387 hir
::ItemKind
::ExternCrate(_
)
388 | hir
::ItemKind
::Use(..)
389 | hir
::ItemKind
::Mod(..)
390 | hir
::ItemKind
::ForeignMod(..)
391 | hir
::ItemKind
::GlobalAsm(..) => {
392 // These sorts of items have no lifetime parameters at all.
393 intravisit
::walk_item(self, item
);
395 hir
::ItemKind
::Static(..) | hir
::ItemKind
::Const(..) => {
396 // No lifetime parameters, but implied 'static.
397 let scope
= Scope
::Elision { elide: Elide::Exact(Region::Static), s: ROOT_SCOPE }
;
398 self.with(scope
, |_
, this
| intravisit
::walk_item(this
, item
));
400 hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { impl_trait_fn: Some(_), .. }
) => {
401 // Currently opaque type declarations are just generated from `impl Trait`
402 // items. Doing anything on this node is irrelevant, as we currently don't need
405 hir
::ItemKind
::TyAlias(_
, ref generics
)
406 | hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy
{
407 impl_trait_fn
: None
, ref generics
, ..
409 | hir
::ItemKind
::Enum(_
, ref generics
)
410 | hir
::ItemKind
::Struct(_
, ref generics
)
411 | hir
::ItemKind
::Union(_
, ref generics
)
412 | hir
::ItemKind
::Trait(_
, _
, ref generics
, ..)
413 | hir
::ItemKind
::TraitAlias(ref generics
, ..)
414 | hir
::ItemKind
::Impl { ref generics, .. }
=> {
415 self.missing_named_lifetime_spots
.push(generics
.into());
417 // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name".
418 // This is not true for other kinds of items.x
419 let track_lifetime_uses
= match item
.kind
{
420 hir
::ItemKind
::Impl { .. }
=> true,
423 // These kinds of items have only early-bound lifetime parameters.
424 let mut index
= if sub_items_have_self_param(&item
.kind
) {
425 1 // Self comes before lifetimes
429 let mut non_lifetime_count
= 0;
430 let lifetimes
= generics
433 .filter_map(|param
| match param
.kind
{
434 GenericParamKind
::Lifetime { .. }
=> {
435 Some(Region
::early(&self.tcx
.hir(), &mut index
, param
))
437 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
438 non_lifetime_count
+= 1;
443 let scope
= Scope
::Binder
{
445 next_early_index
: index
+ non_lifetime_count
,
446 opaque_type_parent
: true,
450 self.with(scope
, |old_scope
, this
| {
451 this
.check_lifetime_params(old_scope
, &generics
.params
);
452 intravisit
::walk_item(this
, item
);
454 self.missing_named_lifetime_spots
.pop();
459 fn visit_foreign_item(&mut self, item
: &'tcx hir
::ForeignItem
<'tcx
>) {
461 hir
::ForeignItemKind
::Fn(ref decl
, _
, ref generics
) => {
462 self.visit_early_late(None
, decl
, generics
, |this
| {
463 intravisit
::walk_foreign_item(this
, item
);
466 hir
::ForeignItemKind
::Static(..) => {
467 intravisit
::walk_foreign_item(self, item
);
469 hir
::ForeignItemKind
::Type
=> {
470 intravisit
::walk_foreign_item(self, item
);
475 fn visit_ty(&mut self, ty
: &'tcx hir
::Ty
<'tcx
>) {
476 debug
!("visit_ty: id={:?} ty={:?}", ty
.hir_id
, ty
);
477 debug
!("visit_ty: ty.kind={:?}", ty
.kind
);
479 hir
::TyKind
::BareFn(ref c
) => {
480 let next_early_index
= self.next_early_index();
481 let was_in_fn_syntax
= self.is_in_fn_syntax
;
482 self.is_in_fn_syntax
= true;
483 let lifetime_span
: Option
<Span
> = c
486 .filter_map(|param
| match param
.kind
{
487 GenericParamKind
::Lifetime { .. }
=> Some(param
.span
),
491 let (span
, span_type
) = if let Some(span
) = lifetime_span
{
492 (span
.shrink_to_hi(), ForLifetimeSpanType
::TypeTail
)
494 (ty
.span
.shrink_to_lo(), ForLifetimeSpanType
::TypeEmpty
)
496 self.missing_named_lifetime_spots
497 .push(MissingLifetimeSpot
::HigherRanked { span, span_type }
);
498 let scope
= Scope
::Binder
{
502 .filter_map(|param
| match param
.kind
{
503 GenericParamKind
::Lifetime { .. }
=> {
504 Some(Region
::late(&self.tcx
.hir(), param
))
511 track_lifetime_uses
: true,
512 opaque_type_parent
: false,
514 self.with(scope
, |old_scope
, this
| {
515 // a bare fn has no bounds, so everything
516 // contained within is scoped within its binder.
517 this
.check_lifetime_params(old_scope
, &c
.generic_params
);
518 intravisit
::walk_ty(this
, ty
);
520 self.missing_named_lifetime_spots
.pop();
521 self.is_in_fn_syntax
= was_in_fn_syntax
;
523 hir
::TyKind
::TraitObject(bounds
, ref lifetime
) => {
524 debug
!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds
, lifetime
);
525 for bound
in bounds
{
526 self.visit_poly_trait_ref(bound
, hir
::TraitBoundModifier
::None
);
528 match lifetime
.name
{
529 LifetimeName
::Implicit
=> {
530 // For types like `dyn Foo`, we should
531 // generate a special form of elided.
532 span_bug
!(ty
.span
, "object-lifetime-default expected, not implicit",);
534 LifetimeName
::ImplicitObjectLifetimeDefault
=> {
535 // If the user does not write *anything*, we
536 // use the object lifetime defaulting
537 // rules. So e.g., `Box<dyn Debug>` becomes
538 // `Box<dyn Debug + 'static>`.
539 self.resolve_object_lifetime_default(lifetime
)
541 LifetimeName
::Underscore
=> {
542 // If the user writes `'_`, we use the *ordinary* elision
543 // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
544 // resolved the same as the `'_` in `&'_ Foo`.
547 self.resolve_elided_lifetimes(vec
![lifetime
])
549 LifetimeName
::Param(_
) | LifetimeName
::Static
=> {
550 // If the user wrote an explicit name, use that.
551 self.visit_lifetime(lifetime
);
553 LifetimeName
::Error
=> {}
556 hir
::TyKind
::Rptr(ref lifetime_ref
, ref mt
) => {
557 self.visit_lifetime(lifetime_ref
);
558 let scope
= Scope
::ObjectLifetimeDefault
{
559 lifetime
: self.map
.defs
.get(&lifetime_ref
.hir_id
).cloned(),
562 self.with(scope
, |_
, this
| this
.visit_ty(&mt
.ty
));
564 hir
::TyKind
::Def(item_id
, lifetimes
) => {
565 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
566 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
567 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
568 // ^ ^ this gets resolved in the scope of
569 // the opaque_ty generics
570 let (generics
, bounds
) = match self.tcx
.hir().expect_item(item_id
.id
).kind
{
571 // Named opaque `impl Trait` types are reached via `TyKind::Path`.
572 // This arm is for `impl Trait` in the types of statics, constants and locals.
573 hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { impl_trait_fn: None, .. }
) => {
574 intravisit
::walk_ty(self, ty
);
577 // RPIT (return position impl trait)
578 hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { ref generics, bounds, .. }
) => {
581 ref i
=> bug
!("`impl Trait` pointed to non-opaque type?? {:#?}", i
),
584 // Resolve the lifetimes that are applied to the opaque type.
585 // These are resolved in the current scope.
586 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
587 // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
588 // ^ ^this gets resolved in the current scope
589 for lifetime
in lifetimes
{
590 if let hir
::GenericArg
::Lifetime(lifetime
) = lifetime
{
591 self.visit_lifetime(lifetime
);
593 // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
594 // and ban them. Type variables instantiated inside binders aren't
595 // well-supported at the moment, so this doesn't work.
596 // In the future, this should be fixed and this error should be removed.
597 let def
= self.map
.defs
.get(&lifetime
.hir_id
).cloned();
598 if let Some(Region
::LateBound(_
, def_id
, _
)) = def
{
599 if let Some(hir_id
) = self.tcx
.hir().as_local_hir_id(def_id
) {
600 // Ensure that the parent of the def is an item, not HRTB
601 let parent_id
= self.tcx
.hir().get_parent_node(hir_id
);
602 let parent_impl_id
= hir
::ImplItemId { hir_id: parent_id }
;
603 let parent_trait_id
= hir
::TraitItemId { hir_id: parent_id }
;
604 let krate
= self.tcx
.hir().krate();
606 if !(krate
.items
.contains_key(&parent_id
)
607 || krate
.impl_items
.contains_key(&parent_impl_id
)
608 || krate
.trait_items
.contains_key(&parent_trait_id
))
614 "`impl Trait` can only capture lifetimes \
615 bound at the fn or impl level"
618 self.uninsert_lifetime_on_error(lifetime
, def
.unwrap());
625 // We want to start our early-bound indices at the end of the parent scope,
626 // not including any parent `impl Trait`s.
627 let mut index
= self.next_early_index_for_opaque_type();
628 debug
!("visit_ty: index = {}", index
);
630 let mut elision
= None
;
631 let mut lifetimes
= FxHashMap
::default();
632 let mut non_lifetime_count
= 0;
633 for param
in generics
.params
{
635 GenericParamKind
::Lifetime { .. }
=> {
636 let (name
, reg
) = Region
::early(&self.tcx
.hir(), &mut index
, ¶m
);
637 let def_id
= if let Region
::EarlyBound(_
, def_id
, _
) = reg
{
642 if let hir
::ParamName
::Plain(param_name
) = name
{
643 if param_name
.name
== kw
::UnderscoreLifetime
{
644 // Pick the elided lifetime "definition" if one exists
645 // and use it to make an elision scope.
646 self.lifetime_uses
.insert(def_id
, LifetimeUseSet
::Many
);
649 lifetimes
.insert(name
, reg
);
652 self.lifetime_uses
.insert(def_id
, LifetimeUseSet
::Many
);
653 lifetimes
.insert(name
, reg
);
656 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
657 non_lifetime_count
+= 1;
661 let next_early_index
= index
+ non_lifetime_count
;
663 if let Some(elision_region
) = elision
{
665 Scope
::Elision { elide: Elide::Exact(elision_region), s: self.scope }
;
666 self.with(scope
, |_old_scope
, this
| {
667 let scope
= Scope
::Binder
{
671 track_lifetime_uses
: true,
672 opaque_type_parent
: false,
674 this
.with(scope
, |_old_scope
, this
| {
675 this
.visit_generics(generics
);
676 for bound
in bounds
{
677 this
.visit_param_bound(bound
);
682 let scope
= Scope
::Binder
{
686 track_lifetime_uses
: true,
687 opaque_type_parent
: false,
689 self.with(scope
, |_old_scope
, this
| {
690 this
.visit_generics(generics
);
691 for bound
in bounds
{
692 this
.visit_param_bound(bound
);
697 _
=> intravisit
::walk_ty(self, ty
),
701 fn visit_trait_item(&mut self, trait_item
: &'tcx hir
::TraitItem
<'tcx
>) {
702 use self::hir
::TraitItemKind
::*;
703 self.missing_named_lifetime_spots
.push((&trait_item
.generics
).into());
704 match trait_item
.kind
{
707 self.visit_early_late(
708 Some(tcx
.hir().get_parent_item(trait_item
.hir_id
)),
710 &trait_item
.generics
,
711 |this
| intravisit
::walk_trait_item(this
, trait_item
),
714 Type(bounds
, ref ty
) => {
715 let generics
= &trait_item
.generics
;
716 let mut index
= self.next_early_index();
717 debug
!("visit_ty: index = {}", index
);
718 let mut non_lifetime_count
= 0;
719 let lifetimes
= generics
722 .filter_map(|param
| match param
.kind
{
723 GenericParamKind
::Lifetime { .. }
=> {
724 Some(Region
::early(&self.tcx
.hir(), &mut index
, param
))
726 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
727 non_lifetime_count
+= 1;
732 let scope
= Scope
::Binder
{
734 next_early_index
: index
+ non_lifetime_count
,
736 track_lifetime_uses
: true,
737 opaque_type_parent
: true,
739 self.with(scope
, |old_scope
, this
| {
740 this
.check_lifetime_params(old_scope
, &generics
.params
);
741 this
.visit_generics(generics
);
742 for bound
in bounds
{
743 this
.visit_param_bound(bound
);
745 if let Some(ty
) = ty
{
751 // Only methods and types support generics.
752 assert
!(trait_item
.generics
.params
.is_empty());
753 intravisit
::walk_trait_item(self, trait_item
);
756 self.missing_named_lifetime_spots
.pop();
759 fn visit_impl_item(&mut self, impl_item
: &'tcx hir
::ImplItem
<'tcx
>) {
760 use self::hir
::ImplItemKind
::*;
761 self.missing_named_lifetime_spots
.push((&impl_item
.generics
).into());
762 match impl_item
.kind
{
765 self.visit_early_late(
766 Some(tcx
.hir().get_parent_item(impl_item
.hir_id
)),
769 |this
| intravisit
::walk_impl_item(this
, impl_item
),
773 let generics
= &impl_item
.generics
;
774 let mut index
= self.next_early_index();
775 let mut non_lifetime_count
= 0;
776 debug
!("visit_ty: index = {}", index
);
777 let lifetimes
= generics
780 .filter_map(|param
| match param
.kind
{
781 GenericParamKind
::Lifetime { .. }
=> {
782 Some(Region
::early(&self.tcx
.hir(), &mut index
, param
))
784 GenericParamKind
::Const { .. }
| GenericParamKind
::Type { .. }
=> {
785 non_lifetime_count
+= 1;
790 let scope
= Scope
::Binder
{
792 next_early_index
: index
+ non_lifetime_count
,
794 track_lifetime_uses
: true,
795 opaque_type_parent
: true,
797 self.with(scope
, |old_scope
, this
| {
798 this
.check_lifetime_params(old_scope
, &generics
.params
);
799 this
.visit_generics(generics
);
803 OpaqueTy(bounds
) => {
804 let generics
= &impl_item
.generics
;
805 let mut index
= self.next_early_index();
806 let mut next_early_index
= index
;
807 debug
!("visit_ty: index = {}", index
);
808 let lifetimes
= generics
811 .filter_map(|param
| match param
.kind
{
812 GenericParamKind
::Lifetime { .. }
=> {
813 Some(Region
::early(&self.tcx
.hir(), &mut index
, param
))
815 GenericParamKind
::Type { .. }
=> {
816 next_early_index
+= 1;
819 GenericParamKind
::Const { .. }
=> {
820 next_early_index
+= 1;
826 let scope
= Scope
::Binder
{
830 track_lifetime_uses
: true,
831 opaque_type_parent
: true,
833 self.with(scope
, |_old_scope
, this
| {
834 this
.visit_generics(generics
);
835 for bound
in bounds
{
836 this
.visit_param_bound(bound
);
841 // Only methods and types support generics.
842 assert
!(impl_item
.generics
.params
.is_empty());
843 intravisit
::walk_impl_item(self, impl_item
);
846 self.missing_named_lifetime_spots
.pop();
849 fn visit_lifetime(&mut self, lifetime_ref
: &'tcx hir
::Lifetime
) {
850 debug
!("visit_lifetime(lifetime_ref={:?})", lifetime_ref
);
851 if lifetime_ref
.is_elided() {
852 self.resolve_elided_lifetimes(vec
![lifetime_ref
]);
855 if lifetime_ref
.is_static() {
856 self.insert_lifetime(lifetime_ref
, Region
::Static
);
859 self.resolve_lifetime_ref(lifetime_ref
);
862 fn visit_path(&mut self, path
: &'tcx hir
::Path
<'tcx
>, _
: hir
::HirId
) {
863 for (i
, segment
) in path
.segments
.iter().enumerate() {
864 let depth
= path
.segments
.len() - i
- 1;
865 if let Some(ref args
) = segment
.args
{
866 self.visit_segment_args(path
.res
, depth
, args
);
871 fn visit_fn_decl(&mut self, fd
: &'tcx hir
::FnDecl
<'tcx
>) {
872 let output
= match fd
.output
{
873 hir
::FnRetTy
::DefaultReturn(_
) => None
,
874 hir
::FnRetTy
::Return(ref ty
) => Some(&**ty
),
876 self.visit_fn_like_elision(&fd
.inputs
, output
);
879 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
<'tcx
>) {
880 check_mixed_explicit_and_in_band_defs(self.tcx
, &generics
.params
);
881 for param
in generics
.params
{
883 GenericParamKind
::Lifetime { .. }
=> {}
884 GenericParamKind
::Type { ref default, .. }
=> {
885 walk_list
!(self, visit_param_bound
, param
.bounds
);
886 if let Some(ref ty
) = default {
890 GenericParamKind
::Const { ref ty, .. }
=> {
891 walk_list
!(self, visit_param_bound
, param
.bounds
);
896 for predicate
in generics
.where_clause
.predicates
{
898 &hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{
901 ref bound_generic_params
,
904 let lifetimes
: FxHashMap
<_
, _
> = bound_generic_params
906 .filter_map(|param
| match param
.kind
{
907 GenericParamKind
::Lifetime { .. }
=> {
908 Some(Region
::late(&self.tcx
.hir(), param
))
913 if !lifetimes
.is_empty() {
914 self.trait_ref_hack
= true;
915 let next_early_index
= self.next_early_index();
916 let scope
= Scope
::Binder
{
920 track_lifetime_uses
: true,
921 opaque_type_parent
: false,
923 let result
= self.with(scope
, |old_scope
, this
| {
924 this
.check_lifetime_params(old_scope
, &bound_generic_params
);
925 this
.visit_ty(&bounded_ty
);
926 walk_list
!(this
, visit_param_bound
, bounds
);
928 self.trait_ref_hack
= false;
931 self.visit_ty(&bounded_ty
);
932 walk_list
!(self, visit_param_bound
, bounds
);
935 &hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{
940 self.visit_lifetime(lifetime
);
941 walk_list
!(self, visit_param_bound
, bounds
);
943 &hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{
948 self.visit_ty(lhs_ty
);
949 self.visit_ty(rhs_ty
);
955 fn visit_poly_trait_ref(
957 trait_ref
: &'tcx hir
::PolyTraitRef
<'tcx
>,
958 _modifier
: hir
::TraitBoundModifier
,
960 debug
!("visit_poly_trait_ref(trait_ref={:?})", trait_ref
);
962 let should_pop_missing_lt
= self.is_trait_ref_fn_scope(trait_ref
);
963 if !self.trait_ref_hack
964 || trait_ref
.bound_generic_params
.iter().any(|param
| match param
.kind
{
965 GenericParamKind
::Lifetime { .. }
=> true,
969 if self.trait_ref_hack
{
974 "nested quantification of lifetimes"
978 let next_early_index
= self.next_early_index();
979 let scope
= Scope
::Binder
{
981 .bound_generic_params
983 .filter_map(|param
| match param
.kind
{
984 GenericParamKind
::Lifetime { .. }
=> {
985 Some(Region
::late(&self.tcx
.hir(), param
))
992 track_lifetime_uses
: true,
993 opaque_type_parent
: false,
995 self.with(scope
, |old_scope
, this
| {
996 this
.check_lifetime_params(old_scope
, &trait_ref
.bound_generic_params
);
997 walk_list
!(this
, visit_generic_param
, trait_ref
.bound_generic_params
);
998 this
.visit_trait_ref(&trait_ref
.trait_ref
);
1001 self.visit_trait_ref(&trait_ref
.trait_ref
);
1003 if should_pop_missing_lt
{
1004 self.missing_named_lifetime_spots
.pop();
1009 #[derive(Copy, Clone, PartialEq)]
1023 fn original_label(span
: Span
) -> Original
{
1024 Original { kind: ShadowKind::Label, span }
1026 fn shadower_label(span
: Span
) -> Shadower
{
1027 Shadower { kind: ShadowKind::Label, span }
1029 fn original_lifetime(span
: Span
) -> Original
{
1030 Original { kind: ShadowKind::Lifetime, span }
1032 fn shadower_lifetime(param
: &hir
::GenericParam
<'_
>) -> Shadower
{
1033 Shadower { kind: ShadowKind::Lifetime, span: param.span }
1037 fn desc(&self) -> &'
static str {
1039 ShadowKind
::Label
=> "label",
1040 ShadowKind
::Lifetime
=> "lifetime",
1045 fn check_mixed_explicit_and_in_band_defs(tcx
: TyCtxt
<'_
>, params
: &[hir
::GenericParam
<'_
>]) {
1046 let lifetime_params
: Vec
<_
> = params
1048 .filter_map(|param
| match param
.kind
{
1049 GenericParamKind
::Lifetime { kind, .. }
=> Some((kind
, param
.span
)),
1053 let explicit
= lifetime_params
.iter().find(|(kind
, _
)| *kind
== LifetimeParamKind
::Explicit
);
1054 let in_band
= lifetime_params
.iter().find(|(kind
, _
)| *kind
== LifetimeParamKind
::InBand
);
1056 if let (Some((_
, explicit_span
)), Some((_
, in_band_span
))) = (explicit
, in_band
) {
1061 "cannot mix in-band and explicit lifetime definitions"
1063 .span_label(*in_band_span
, "in-band lifetime definition here")
1064 .span_label(*explicit_span
, "explicit lifetime definition here")
1069 fn signal_shadowing_problem(tcx
: TyCtxt
<'_
>, name
: ast
::Name
, orig
: Original
, shadower
: Shadower
) {
1070 let mut err
= if let (ShadowKind
::Lifetime
, ShadowKind
::Lifetime
) = (orig
.kind
, shadower
.kind
) {
1071 // lifetime/lifetime shadowing is an error
1076 "{} name `{}` shadows a \
1077 {} name that is already in scope",
1078 shadower
.kind
.desc(),
1083 // shadowing involving a label is only a warning, due to issues with
1084 // labels and lifetimes not being macro-hygienic.
1085 tcx
.sess
.struct_span_warn(
1088 "{} name `{}` shadows a \
1089 {} name that is already in scope",
1090 shadower
.kind
.desc(),
1096 err
.span_label(orig
.span
, "first declared here");
1097 err
.span_label(shadower
.span
, format
!("lifetime {} already in scope", name
));
1101 // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
1102 // if one of the label shadows a lifetime or another label.
1103 fn extract_labels(ctxt
: &mut LifetimeContext
<'_
, '_
>, body
: &hir
::Body
<'_
>) {
1104 struct GatherLabels
<'a
, 'tcx
> {
1106 scope
: ScopeRef
<'a
>,
1107 labels_in_fn
: &'a
mut Vec
<ast
::Ident
>,
1111 GatherLabels { tcx: ctxt.tcx, scope: ctxt.scope, labels_in_fn: &mut ctxt.labels_in_fn }
;
1112 gather
.visit_body(body
);
1114 impl<'v
, 'a
, 'tcx
> Visitor
<'v
> for GatherLabels
<'a
, 'tcx
> {
1115 type Map
= intravisit
::ErasedMap
<'v
>;
1117 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
1118 NestedVisitorMap
::None
1121 fn visit_expr(&mut self, ex
: &hir
::Expr
<'_
>) {
1122 if let Some(label
) = expression_label(ex
) {
1123 for prior_label
in &self.labels_in_fn
[..] {
1124 // FIXME (#24278): non-hygienic comparison
1125 if label
.name
== prior_label
.name
{
1126 signal_shadowing_problem(
1129 original_label(prior_label
.span
),
1130 shadower_label(label
.span
),
1135 check_if_label_shadows_lifetime(self.tcx
, self.scope
, label
);
1137 self.labels_in_fn
.push(label
);
1139 intravisit
::walk_expr(self, ex
)
1143 fn expression_label(ex
: &hir
::Expr
<'_
>) -> Option
<ast
::Ident
> {
1144 if let hir
::ExprKind
::Loop(_
, Some(label
), _
) = ex
.kind { Some(label.ident) }
else { None }
1147 fn check_if_label_shadows_lifetime(
1149 mut scope
: ScopeRef
<'_
>,
1154 Scope
::Body { s, .. }
1155 | Scope
::Elision { s, .. }
1156 | Scope
::ObjectLifetimeDefault { s, .. }
=> {
1164 Scope
::Binder { ref lifetimes, s, .. }
=> {
1165 // FIXME (#24278): non-hygienic comparison
1167 lifetimes
.get(&hir
::ParamName
::Plain(label
.normalize_to_macros_2_0()))
1169 let hir_id
= tcx
.hir().as_local_hir_id(def
.id().unwrap()).unwrap();
1171 signal_shadowing_problem(
1174 original_lifetime(tcx
.hir().span(hir_id
)),
1175 shadower_label(label
.span
),
1186 fn compute_object_lifetime_defaults(tcx
: TyCtxt
<'_
>) -> HirIdMap
<Vec
<ObjectLifetimeDefault
>> {
1187 let mut map
= HirIdMap
::default();
1188 for item
in tcx
.hir().krate().items
.values() {
1190 hir
::ItemKind
::Struct(_
, ref generics
)
1191 | hir
::ItemKind
::Union(_
, ref generics
)
1192 | hir
::ItemKind
::Enum(_
, ref generics
)
1193 | hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy
{
1194 ref generics
, impl_trait_fn
: None
, ..
1196 | hir
::ItemKind
::TyAlias(_
, ref generics
)
1197 | hir
::ItemKind
::Trait(_
, _
, ref generics
, ..) => {
1198 let result
= object_lifetime_defaults_for_item(tcx
, generics
);
1201 if attr
::contains_name(&item
.attrs
, sym
::rustc_object_lifetime_default
) {
1202 let object_lifetime_default_reprs
: String
= result
1204 .map(|set
| match *set
{
1205 Set1
::Empty
=> "BaseDefault".into(),
1206 Set1
::One(Region
::Static
) => "'static".into(),
1207 Set1
::One(Region
::EarlyBound(mut i
, _
, _
)) => generics
1210 .find_map(|param
| match param
.kind
{
1211 GenericParamKind
::Lifetime { .. }
=> {
1213 return Some(param
.name
.ident().to_string().into());
1221 Set1
::One(_
) => bug
!(),
1222 Set1
::Many
=> "Ambiguous".into(),
1224 .collect
::<Vec
<Cow
<'
static, str>>>()
1226 tcx
.sess
.span_err(item
.span
, &object_lifetime_default_reprs
);
1229 map
.insert(item
.hir_id
, result
);
1237 /// Scan the bounds and where-clauses on parameters to extract bounds
1238 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1239 /// for each type parameter.
1240 fn object_lifetime_defaults_for_item(
1242 generics
: &hir
::Generics
<'_
>,
1243 ) -> Vec
<ObjectLifetimeDefault
> {
1244 fn add_bounds(set
: &mut Set1
<hir
::LifetimeName
>, bounds
: &[hir
::GenericBound
<'_
>]) {
1245 for bound
in bounds
{
1246 if let hir
::GenericBound
::Outlives(ref lifetime
) = *bound
{
1247 set
.insert(lifetime
.name
.normalize_to_macros_2_0());
1255 .filter_map(|param
| match param
.kind
{
1256 GenericParamKind
::Lifetime { .. }
=> None
,
1257 GenericParamKind
::Type { .. }
=> {
1258 let mut set
= Set1
::Empty
;
1260 add_bounds(&mut set
, ¶m
.bounds
);
1262 let param_def_id
= tcx
.hir().local_def_id(param
.hir_id
);
1263 for predicate
in generics
.where_clause
.predicates
{
1264 // Look for `type: ...` where clauses.
1265 let data
= match *predicate
{
1266 hir
::WherePredicate
::BoundPredicate(ref data
) => data
,
1270 // Ignore `for<'a> type: ...` as they can change what
1271 // lifetimes mean (although we could "just" handle it).
1272 if !data
.bound_generic_params
.is_empty() {
1276 let res
= match data
.bounded_ty
.kind
{
1277 hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) => path
.res
,
1281 if res
== Res
::Def(DefKind
::TyParam
, param_def_id
) {
1282 add_bounds(&mut set
, &data
.bounds
);
1287 Set1
::Empty
=> Set1
::Empty
,
1288 Set1
::One(name
) => {
1289 if name
== hir
::LifetimeName
::Static
{
1290 Set1
::One(Region
::Static
)
1295 .filter_map(|param
| match param
.kind
{
1296 GenericParamKind
::Lifetime { .. }
=> Some((
1298 hir
::LifetimeName
::Param(param
.name
),
1299 LifetimeDefOrigin
::from_param(param
),
1304 .find(|&(_
, (_
, lt_name
, _
))| lt_name
== name
)
1305 .map_or(Set1
::Many
, |(i
, (id
, _
, origin
))| {
1306 let def_id
= tcx
.hir().local_def_id(id
);
1307 Set1
::One(Region
::EarlyBound(i
as u32, def_id
, origin
))
1311 Set1
::Many
=> Set1
::Many
,
1314 GenericParamKind
::Const { .. }
=> {
1315 // Generic consts don't impose any constraints.
1322 impl<'a
, 'tcx
> LifetimeContext
<'a
, 'tcx
> {
1323 // FIXME(#37666) this works around a limitation in the region inferencer
1324 fn hack
<F
>(&mut self, f
: F
)
1326 F
: for<'b
> FnOnce(&mut LifetimeContext
<'b
, 'tcx
>),
1331 fn with
<F
>(&mut self, wrap_scope
: Scope
<'_
>, f
: F
)
1333 F
: for<'b
> FnOnce(ScopeRef
<'_
>, &mut LifetimeContext
<'b
, 'tcx
>),
1335 let LifetimeContext { tcx, map, lifetime_uses, .. }
= self;
1336 let labels_in_fn
= take(&mut self.labels_in_fn
);
1337 let xcrate_object_lifetime_defaults
= take(&mut self.xcrate_object_lifetime_defaults
);
1338 let missing_named_lifetime_spots
= take(&mut self.missing_named_lifetime_spots
);
1339 let mut this
= LifetimeContext
{
1343 trait_ref_hack
: self.trait_ref_hack
,
1344 is_in_fn_syntax
: self.is_in_fn_syntax
,
1346 xcrate_object_lifetime_defaults
,
1348 missing_named_lifetime_spots
,
1350 debug
!("entering scope {:?}", this
.scope
);
1351 f(self.scope
, &mut this
);
1352 this
.check_uses_for_lifetimes_defined_by_scope();
1353 debug
!("exiting scope {:?}", this
.scope
);
1354 self.labels_in_fn
= this
.labels_in_fn
;
1355 self.xcrate_object_lifetime_defaults
= this
.xcrate_object_lifetime_defaults
;
1356 self.missing_named_lifetime_spots
= this
.missing_named_lifetime_spots
;
1359 /// helper method to determine the span to remove when suggesting the
1360 /// deletion of a lifetime
1361 fn lifetime_deletion_span(
1364 generics
: &hir
::Generics
<'_
>,
1366 generics
.params
.iter().enumerate().find_map(|(i
, param
)| {
1367 if param
.name
.ident() == name
{
1368 let mut in_band
= false;
1369 if let hir
::GenericParamKind
::Lifetime { kind }
= param
.kind
{
1370 if let hir
::LifetimeParamKind
::InBand
= kind
{
1377 if generics
.params
.len() == 1 {
1378 // if sole lifetime, remove the entire `<>` brackets
1381 // if removing within `<>` brackets, we also want to
1382 // delete a leading or trailing comma as appropriate
1383 if i
>= generics
.params
.len() - 1 {
1384 Some(generics
.params
[i
- 1].span
.shrink_to_hi().to(param
.span
))
1386 Some(param
.span
.to(generics
.params
[i
+ 1].span
.shrink_to_lo()))
1396 // helper method to issue suggestions from `fn rah<'a>(&'a T)` to `fn rah(&T)`
1397 // or from `fn rah<'a>(T<'a>)` to `fn rah(T<'_>)`
1398 fn suggest_eliding_single_use_lifetime(
1400 err
: &mut DiagnosticBuilder
<'_
>,
1402 lifetime
: &hir
::Lifetime
,
1404 let name
= lifetime
.name
.ident();
1405 let mut remove_decl
= None
;
1406 if let Some(parent_def_id
) = self.tcx
.parent(def_id
) {
1407 if let Some(generics
) = self.tcx
.hir().get_generics(parent_def_id
) {
1408 remove_decl
= self.lifetime_deletion_span(name
, generics
);
1412 let mut remove_use
= None
;
1413 let mut elide_use
= None
;
1414 let mut find_arg_use_span
= |inputs
: &[hir
::Ty
<'_
>]| {
1415 for input
in inputs
{
1417 hir
::TyKind
::Rptr(lt
, _
) => {
1418 if lt
.name
.ident() == name
{
1419 // include the trailing whitespace between the lifetime and type names
1420 let lt_through_ty_span
= lifetime
.span
.to(input
.span
.shrink_to_hi());
1425 .span_until_non_whitespace(lt_through_ty_span
),
1430 hir
::TyKind
::Path(ref qpath
) => {
1431 if let QPath
::Resolved(_
, path
) = qpath
{
1432 let last_segment
= &path
.segments
[path
.segments
.len() - 1];
1433 let generics
= last_segment
.generic_args();
1434 for arg
in generics
.args
.iter() {
1435 if let GenericArg
::Lifetime(lt
) = arg
{
1436 if lt
.name
.ident() == name
{
1437 elide_use
= Some(lt
.span
);
1449 if let Node
::Lifetime(hir_lifetime
) = self.tcx
.hir().get(lifetime
.hir_id
) {
1450 if let Some(parent
) =
1451 self.tcx
.hir().find(self.tcx
.hir().get_parent_item(hir_lifetime
.hir_id
))
1454 Node
::Item(item
) => {
1455 if let hir
::ItemKind
::Fn(sig
, _
, _
) = &item
.kind
{
1456 find_arg_use_span(sig
.decl
.inputs
);
1459 Node
::ImplItem(impl_item
) => {
1460 if let hir
::ImplItemKind
::Fn(sig
, _
) = &impl_item
.kind
{
1461 find_arg_use_span(sig
.decl
.inputs
);
1469 let msg
= "elide the single-use lifetime";
1470 match (remove_decl
, remove_use
, elide_use
) {
1471 (Some(decl_span
), Some(use_span
), None
) => {
1472 // if both declaration and use deletion spans start at the same
1473 // place ("start at" because the latter includes trailing
1474 // whitespace), then this is an in-band lifetime
1475 if decl_span
.shrink_to_lo() == use_span
.shrink_to_lo() {
1476 err
.span_suggestion(
1480 Applicability
::MachineApplicable
,
1483 err
.multipart_suggestion(
1485 vec
![(decl_span
, String
::new()), (use_span
, String
::new())],
1486 Applicability
::MachineApplicable
,
1490 (Some(decl_span
), None
, Some(use_span
)) => {
1491 err
.multipart_suggestion(
1493 vec
![(decl_span
, String
::new()), (use_span
, "'_".to_owned())],
1494 Applicability
::MachineApplicable
,
1501 fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
1502 let defined_by
= match self.scope
{
1503 Scope
::Binder { lifetimes, .. }
=> lifetimes
,
1505 debug
!("check_uses_for_lifetimes_defined_by_scope: not in a binder scope");
1510 let mut def_ids
: Vec
<_
> = defined_by
1512 .flat_map(|region
| match region
{
1513 Region
::EarlyBound(_
, def_id
, _
)
1514 | Region
::LateBound(_
, def_id
, _
)
1515 | Region
::Free(_
, def_id
) => Some(*def_id
),
1517 Region
::LateBoundAnon(..) | Region
::Static
=> None
,
1521 // ensure that we issue lints in a repeatable order
1522 def_ids
.sort_by_cached_key(|&def_id
| self.tcx
.def_path_hash(def_id
));
1524 for def_id
in def_ids
{
1525 debug
!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id
);
1527 let lifetimeuseset
= self.lifetime_uses
.remove(&def_id
);
1530 "check_uses_for_lifetimes_defined_by_scope: lifetimeuseset = {:?}",
1534 match lifetimeuseset
{
1535 Some(LifetimeUseSet
::One(lifetime
)) => {
1536 let hir_id
= self.tcx
.hir().as_local_hir_id(def_id
).unwrap();
1537 debug
!("hir id first={:?}", hir_id
);
1538 if let Some((id
, span
, name
)) = match self.tcx
.hir().get(hir_id
) {
1539 Node
::Lifetime(hir_lifetime
) => Some((
1540 hir_lifetime
.hir_id
,
1542 hir_lifetime
.name
.ident(),
1544 Node
::GenericParam(param
) => {
1545 Some((param
.hir_id
, param
.span
, param
.name
.ident()))
1549 debug
!("id = {:?} span = {:?} name = {:?}", id
, span
, name
);
1550 if name
.name
== kw
::UnderscoreLifetime
{
1554 if let Some(parent_def_id
) = self.tcx
.parent(def_id
) {
1555 if let Some(parent_hir_id
) =
1556 self.tcx
.hir().as_local_hir_id(parent_def_id
)
1558 // lifetimes in `derive` expansions don't count (Issue #53738)
1562 .attrs(parent_hir_id
)
1564 .any(|attr
| attr
.check_name(sym
::automatically_derived
))
1571 self.tcx
.struct_span_lint_hir(
1572 lint
::builtin
::SINGLE_USE_LIFETIMES
,
1576 let mut err
= lint
.build(&format
!(
1577 "lifetime parameter `{}` only used once",
1580 if span
== lifetime
.span
{
1581 // spans are the same for in-band lifetime declarations
1582 err
.span_label(span
, "this lifetime is only used here");
1584 err
.span_label(span
, "this lifetime...");
1585 err
.span_label(lifetime
.span
, "...is used only here");
1587 self.suggest_eliding_single_use_lifetime(
1588 &mut err
, def_id
, lifetime
,
1595 Some(LifetimeUseSet
::Many
) => {
1596 debug
!("not one use lifetime");
1599 let hir_id
= self.tcx
.hir().as_local_hir_id(def_id
).unwrap();
1600 if let Some((id
, span
, name
)) = match self.tcx
.hir().get(hir_id
) {
1601 Node
::Lifetime(hir_lifetime
) => Some((
1602 hir_lifetime
.hir_id
,
1604 hir_lifetime
.name
.ident(),
1606 Node
::GenericParam(param
) => {
1607 Some((param
.hir_id
, param
.span
, param
.name
.ident()))
1611 debug
!("id ={:?} span = {:?} name = {:?}", id
, span
, name
);
1612 self.tcx
.struct_span_lint_hir(
1613 lint
::builtin
::UNUSED_LIFETIMES
,
1618 .build(&format
!("lifetime parameter `{}` never used", name
));
1619 if let Some(parent_def_id
) = self.tcx
.parent(def_id
) {
1620 if let Some(generics
) =
1621 self.tcx
.hir().get_generics(parent_def_id
)
1623 let unused_lt_span
=
1624 self.lifetime_deletion_span(name
, generics
);
1625 if let Some(span
) = unused_lt_span
{
1626 err
.span_suggestion(
1628 "elide the unused lifetime",
1630 Applicability
::MachineApplicable
,
1644 /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1646 /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1647 /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1648 /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1652 /// fn foo<'a,'b,'c,T:Trait<'b>>(...)
1654 /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1655 /// lifetimes may be interspersed together.
1657 /// If early bound lifetimes are present, we separate them into their own list (and likewise
1658 /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1659 /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1660 /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1661 /// ordering is not important there.
1662 fn visit_early_late
<F
>(
1664 parent_id
: Option
<hir
::HirId
>,
1665 decl
: &'tcx hir
::FnDecl
<'tcx
>,
1666 generics
: &'tcx hir
::Generics
<'tcx
>,
1669 F
: for<'b
, 'c
> FnOnce(&'b
mut LifetimeContext
<'c
, 'tcx
>),
1671 insert_late_bound_lifetimes(self.map
, decl
, generics
);
1673 // Find the start of nested early scopes, e.g., in methods.
1675 if let Some(parent_id
) = parent_id
{
1676 let parent
= self.tcx
.hir().expect_item(parent_id
);
1677 if sub_items_have_self_param(&parent
.kind
) {
1678 index
+= 1; // Self comes before lifetimes
1681 hir
::ItemKind
::Trait(_
, _
, ref generics
, ..)
1682 | hir
::ItemKind
::Impl { ref generics, .. }
=> {
1683 index
+= generics
.params
.len() as u32;
1689 let mut non_lifetime_count
= 0;
1690 let lifetimes
= generics
1693 .filter_map(|param
| match param
.kind
{
1694 GenericParamKind
::Lifetime { .. }
=> {
1695 if self.map
.late_bound
.contains(¶m
.hir_id
) {
1696 Some(Region
::late(&self.tcx
.hir(), param
))
1698 Some(Region
::early(&self.tcx
.hir(), &mut index
, param
))
1701 GenericParamKind
::Type { .. }
| GenericParamKind
::Const { .. }
=> {
1702 non_lifetime_count
+= 1;
1707 let next_early_index
= index
+ non_lifetime_count
;
1709 let scope
= Scope
::Binder
{
1713 opaque_type_parent
: true,
1714 track_lifetime_uses
: false,
1716 self.with(scope
, move |old_scope
, this
| {
1717 this
.check_lifetime_params(old_scope
, &generics
.params
);
1718 this
.hack(walk
); // FIXME(#37666) workaround in place of `walk(this)`
1722 fn next_early_index_helper(&self, only_opaque_type_parent
: bool
) -> u32 {
1723 let mut scope
= self.scope
;
1726 Scope
::Root
=> return 0,
1728 Scope
::Binder { next_early_index, opaque_type_parent, .. }
1729 if (!only_opaque_type_parent
|| opaque_type_parent
) =>
1731 return next_early_index
;
1734 Scope
::Binder { s, .. }
1735 | Scope
::Body { s, .. }
1736 | Scope
::Elision { s, .. }
1737 | Scope
::ObjectLifetimeDefault { s, .. }
=> scope
= s
,
1742 /// Returns the next index one would use for an early-bound-region
1743 /// if extending the current scope.
1744 fn next_early_index(&self) -> u32 {
1745 self.next_early_index_helper(true)
1748 /// Returns the next index one would use for an `impl Trait` that
1749 /// is being converted into an opaque type alias `impl Trait`. This will be the
1750 /// next early index from the enclosing item, for the most
1751 /// part. See the `opaque_type_parent` field for more info.
1752 fn next_early_index_for_opaque_type(&self) -> u32 {
1753 self.next_early_index_helper(false)
1756 fn resolve_lifetime_ref(&mut self, lifetime_ref
: &'tcx hir
::Lifetime
) {
1757 debug
!("resolve_lifetime_ref(lifetime_ref={:?})", lifetime_ref
);
1759 // If we've already reported an error, just ignore `lifetime_ref`.
1760 if let LifetimeName
::Error
= lifetime_ref
.name
{
1764 // Walk up the scope chain, tracking the number of fn scopes
1765 // that we pass through, until we find a lifetime with the
1766 // given name or we run out of scopes.
1768 let mut late_depth
= 0;
1769 let mut scope
= self.scope
;
1770 let mut outermost_body
= None
;
1773 Scope
::Body { id, s }
=> {
1774 outermost_body
= Some(id
);
1782 Scope
::Binder { ref lifetimes, s, .. }
=> {
1783 match lifetime_ref
.name
{
1784 LifetimeName
::Param(param_name
) => {
1785 if let Some(&def
) = lifetimes
.get(¶m_name
.normalize_to_macros_2_0())
1787 break Some(def
.shifted(late_depth
));
1790 _
=> bug
!("expected LifetimeName::Param"),
1797 Scope
::Elision { s, .. }
| Scope
::ObjectLifetimeDefault { s, .. }
=> {
1803 if let Some(mut def
) = result
{
1804 if let Region
::EarlyBound(..) = def
{
1805 // Do not free early-bound regions, only late-bound ones.
1806 } else if let Some(body_id
) = outermost_body
{
1807 let fn_id
= self.tcx
.hir().body_owner(body_id
);
1808 match self.tcx
.hir().get(fn_id
) {
1809 Node
::Item(&hir
::Item { kind: hir::ItemKind::Fn(..), .. }
)
1810 | Node
::TraitItem(&hir
::TraitItem
{
1811 kind
: hir
::TraitItemKind
::Fn(..), ..
1813 | Node
::ImplItem(&hir
::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }
) => {
1814 let scope
= self.tcx
.hir().local_def_id(fn_id
);
1815 def
= Region
::Free(scope
, def
.id().unwrap());
1821 // Check for fn-syntax conflicts with in-band lifetime definitions
1822 if self.is_in_fn_syntax
{
1824 Region
::EarlyBound(_
, _
, LifetimeDefOrigin
::InBand
)
1825 | Region
::LateBound(_
, _
, LifetimeDefOrigin
::InBand
) => {
1830 "lifetimes used in `fn` or `Fn` syntax must be \
1831 explicitly declared using `<...>` binders"
1833 .span_label(lifetime_ref
.span
, "in-band lifetime definition")
1838 | Region
::EarlyBound(
1841 LifetimeDefOrigin
::ExplicitOrElided
| LifetimeDefOrigin
::Error
,
1843 | Region
::LateBound(
1846 LifetimeDefOrigin
::ExplicitOrElided
| LifetimeDefOrigin
::Error
,
1848 | Region
::LateBoundAnon(..)
1849 | Region
::Free(..) => {}
1853 self.insert_lifetime(lifetime_ref
, def
);
1855 self.emit_undeclared_lifetime_error(lifetime_ref
);
1859 fn visit_segment_args(
1863 generic_args
: &'tcx hir
::GenericArgs
<'tcx
>,
1866 "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})",
1867 res
, depth
, generic_args
,
1870 if generic_args
.parenthesized
{
1871 let was_in_fn_syntax
= self.is_in_fn_syntax
;
1872 self.is_in_fn_syntax
= true;
1873 self.visit_fn_like_elision(generic_args
.inputs(), Some(generic_args
.bindings
[0].ty()));
1874 self.is_in_fn_syntax
= was_in_fn_syntax
;
1878 let mut elide_lifetimes
= true;
1879 let lifetimes
= generic_args
1882 .filter_map(|arg
| match arg
{
1883 hir
::GenericArg
::Lifetime(lt
) => {
1884 if !lt
.is_elided() {
1885 elide_lifetimes
= false;
1892 if elide_lifetimes
{
1893 self.resolve_elided_lifetimes(lifetimes
);
1895 lifetimes
.iter().for_each(|lt
| self.visit_lifetime(lt
));
1898 // Figure out if this is a type/trait segment,
1899 // which requires object lifetime defaults.
1900 let parent_def_id
= |this
: &mut Self, def_id
: DefId
| {
1901 let def_key
= this
.tcx
.def_key(def_id
);
1902 DefId { krate: def_id.krate, index: def_key.parent.expect("missing parent") }
1904 let type_def_id
= match res
{
1905 Res
::Def(DefKind
::AssocTy
, def_id
) if depth
== 1 => Some(parent_def_id(self, def_id
)),
1906 Res
::Def(DefKind
::Variant
, def_id
) if depth
== 0 => Some(parent_def_id(self, def_id
)),
1914 ) if depth
== 0 => Some(def_id
),
1918 debug
!("visit_segment_args: type_def_id={:?}", type_def_id
);
1920 // Compute a vector of defaults, one for each type parameter,
1921 // per the rules given in RFCs 599 and 1156. Example:
1924 // struct Foo<'a, T: 'a, U> { }
1927 // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1928 // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1929 // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1932 // Therefore, we would compute `object_lifetime_defaults` to a
1933 // vector like `['x, 'static]`. Note that the vector only
1934 // includes type parameters.
1935 let object_lifetime_defaults
= type_def_id
.map_or(vec
![], |def_id
| {
1937 let mut scope
= self.scope
;
1940 Scope
::Root
=> break false,
1942 Scope
::Body { .. }
=> break true,
1944 Scope
::Binder { s, .. }
1945 | Scope
::Elision { s, .. }
1946 | Scope
::ObjectLifetimeDefault { s, .. }
=> {
1953 let map
= &self.map
;
1954 let unsubst
= if let Some(id
) = self.tcx
.hir().as_local_hir_id(def_id
) {
1955 &map
.object_lifetime_defaults
[&id
]
1958 self.xcrate_object_lifetime_defaults
.entry(def_id
).or_insert_with(|| {
1959 tcx
.generics_of(def_id
)
1962 .filter_map(|param
| match param
.kind
{
1963 GenericParamDefKind
::Type { object_lifetime_default, .. }
=> {
1964 Some(object_lifetime_default
)
1966 GenericParamDefKind
::Lifetime
| GenericParamDefKind
::Const
=> None
,
1971 debug
!("visit_segment_args: unsubst={:?}", unsubst
);
1974 .map(|set
| match *set
{
1979 Some(Region
::Static
)
1983 let lifetimes
= generic_args
.args
.iter().filter_map(|arg
| match arg
{
1984 GenericArg
::Lifetime(lt
) => Some(lt
),
1987 r
.subst(lifetimes
, map
)
1994 debug
!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults
);
1997 for arg
in generic_args
.args
{
1999 GenericArg
::Lifetime(_
) => {}
2000 GenericArg
::Type(ty
) => {
2001 if let Some(<
) = object_lifetime_defaults
.get(i
) {
2002 let scope
= Scope
::ObjectLifetimeDefault { lifetime: lt, s: self.scope }
;
2003 self.with(scope
, |_
, this
| this
.visit_ty(ty
));
2009 GenericArg
::Const(ct
) => {
2010 self.visit_anon_const(&ct
.value
);
2015 // Hack: when resolving the type `XX` in binding like `dyn
2016 // Foo<'b, Item = XX>`, the current object-lifetime default
2017 // would be to examine the trait `Foo` to check whether it has
2018 // a lifetime bound declared on `Item`. e.g., if `Foo` is
2019 // declared like so, then the default object lifetime bound in
2020 // `XX` should be `'b`:
2028 // but if we just have `type Item;`, then it would be
2029 // `'static`. However, we don't get all of this logic correct.
2031 // Instead, we do something hacky: if there are no lifetime parameters
2032 // to the trait, then we simply use a default object lifetime
2033 // bound of `'static`, because there is no other possibility. On the other hand,
2034 // if there ARE lifetime parameters, then we require the user to give an
2035 // explicit bound for now.
2037 // This is intended to leave room for us to implement the
2038 // correct behavior in the future.
2039 let has_lifetime_parameter
= generic_args
.args
.iter().any(|arg
| match arg
{
2040 GenericArg
::Lifetime(_
) => true,
2044 // Resolve lifetimes found in the type `XX` from `Item = XX` bindings.
2045 for b
in generic_args
.bindings
{
2046 let scope
= Scope
::ObjectLifetimeDefault
{
2047 lifetime
: if has_lifetime_parameter { None }
else { Some(Region::Static) }
,
2050 self.with(scope
, |_
, this
| this
.visit_assoc_type_binding(b
));
2054 fn visit_fn_like_elision(
2056 inputs
: &'tcx
[hir
::Ty
<'tcx
>],
2057 output
: Option
<&'tcx hir
::Ty
<'tcx
>>,
2059 debug
!("visit_fn_like_elision: enter");
2060 let mut arg_elide
= Elide
::FreshLateAnon(Cell
::new(0));
2061 let arg_scope
= Scope
::Elision { elide: arg_elide.clone(), s: self.scope }
;
2062 self.with(arg_scope
, |_
, this
| {
2063 for input
in inputs
{
2064 this
.visit_ty(input
);
2067 Scope
::Elision { ref elide, .. }
=> {
2068 arg_elide
= elide
.clone();
2074 let output
= match output
{
2079 debug
!("visit_fn_like_elision: determine output");
2081 // Figure out if there's a body we can get argument names from,
2082 // and whether there's a `self` argument (treated specially).
2083 let mut assoc_item_kind
= None
;
2084 let mut impl_self
= None
;
2085 let parent
= self.tcx
.hir().get_parent_node(output
.hir_id
);
2086 let body
= match self.tcx
.hir().get(parent
) {
2087 // `fn` definitions and methods.
2088 Node
::Item(&hir
::Item { kind: hir::ItemKind::Fn(.., body), .. }
) => Some(body
),
2090 Node
::TraitItem(&hir
::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }
) => {
2091 if let hir
::ItemKind
::Trait(.., ref trait_items
) =
2092 self.tcx
.hir().expect_item(self.tcx
.hir().get_parent_item(parent
)).kind
2095 trait_items
.iter().find(|ti
| ti
.id
.hir_id
== parent
).map(|ti
| ti
.kind
);
2098 hir
::TraitFn
::Required(_
) => None
,
2099 hir
::TraitFn
::Provided(body
) => Some(body
),
2103 Node
::ImplItem(&hir
::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }
) => {
2104 if let hir
::ItemKind
::Impl { ref self_ty, ref items, .. }
=
2105 self.tcx
.hir().expect_item(self.tcx
.hir().get_parent_item(parent
)).kind
2107 impl_self
= Some(self_ty
);
2109 items
.iter().find(|ii
| ii
.id
.hir_id
== parent
).map(|ii
| ii
.kind
);
2114 // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
2115 Node
::ForeignItem(_
) | Node
::Ty(_
) | Node
::TraitRef(_
) => None
,
2116 // Everything else (only closures?) doesn't
2117 // actually enjoy elision in return types.
2119 self.visit_ty(output
);
2124 let has_self
= match assoc_item_kind
{
2125 Some(hir
::AssocItemKind
::Fn { has_self }
) => has_self
,
2129 // In accordance with the rules for lifetime elision, we can determine
2130 // what region to use for elision in the output type in two ways.
2131 // First (determined here), if `self` is by-reference, then the
2132 // implied output region is the region of the self parameter.
2134 struct SelfVisitor
<'a
> {
2135 map
: &'a NamedRegionMap
,
2136 impl_self
: Option
<&'a hir
::TyKind
<'a
>>,
2137 lifetime
: Set1
<Region
>,
2140 impl SelfVisitor
<'_
> {
2141 // Look for `self: &'a Self` - also desugared from `&'a self`,
2142 // and if that matches, use it for elision and return early.
2143 fn is_self_ty(&self, res
: Res
) -> bool
{
2144 if let Res
::SelfTy(..) = res
{
2148 // Can't always rely on literal (or implied) `Self` due
2149 // to the way elision rules were originally specified.
2150 if let Some(&hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
))) =
2154 // Whitelist the types that unambiguously always
2155 // result in the same type constructor being used
2156 // (it can't differ between `Self` and `self`).
2157 Res
::Def(DefKind
::Struct
| DefKind
::Union
| DefKind
::Enum
, _
)
2158 | Res
::PrimTy(_
) => return res
== path
.res
,
2167 impl<'a
> Visitor
<'a
> for SelfVisitor
<'a
> {
2168 type Map
= intravisit
::ErasedMap
<'a
>;
2170 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
2171 NestedVisitorMap
::None
2174 fn visit_ty(&mut self, ty
: &'a hir
::Ty
<'a
>) {
2175 if let hir
::TyKind
::Rptr(lifetime_ref
, ref mt
) = ty
.kind
{
2176 if let hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) = mt
.ty
.kind
2178 if self.is_self_ty(path
.res
) {
2179 if let Some(lifetime
) = self.map
.defs
.get(&lifetime_ref
.hir_id
) {
2180 self.lifetime
.insert(*lifetime
);
2185 intravisit
::walk_ty(self, ty
)
2189 let mut visitor
= SelfVisitor
{
2191 impl_self
: impl_self
.map(|ty
| &ty
.kind
),
2192 lifetime
: Set1
::Empty
,
2194 visitor
.visit_ty(&inputs
[0]);
2195 if let Set1
::One(lifetime
) = visitor
.lifetime
{
2196 let scope
= Scope
::Elision { elide: Elide::Exact(lifetime), s: self.scope }
;
2197 self.with(scope
, |_
, this
| this
.visit_ty(output
));
2202 // Second, if there was exactly one lifetime (either a substitution or a
2203 // reference) in the arguments, then any anonymous regions in the output
2204 // have that lifetime.
2205 let mut possible_implied_output_region
= None
;
2206 let mut lifetime_count
= 0;
2207 let arg_lifetimes
= inputs
2210 .skip(has_self
as usize)
2212 let mut gather
= GatherLifetimes
{
2214 outer_index
: ty
::INNERMOST
,
2215 have_bound_regions
: false,
2216 lifetimes
: Default
::default(),
2218 gather
.visit_ty(input
);
2220 lifetime_count
+= gather
.lifetimes
.len();
2222 if lifetime_count
== 1 && gather
.lifetimes
.len() == 1 {
2223 // there's a chance that the unique lifetime of this
2224 // iteration will be the appropriate lifetime for output
2225 // parameters, so lets store it.
2226 possible_implied_output_region
= gather
.lifetimes
.iter().cloned().next();
2229 ElisionFailureInfo
{
2232 lifetime_count
: gather
.lifetimes
.len(),
2233 have_bound_regions
: gather
.have_bound_regions
,
2239 let elide
= if lifetime_count
== 1 {
2240 Elide
::Exact(possible_implied_output_region
.unwrap())
2242 Elide
::Error(arg_lifetimes
)
2245 debug
!("visit_fn_like_elision: elide={:?}", elide
);
2247 let scope
= Scope
::Elision { elide, s: self.scope }
;
2248 self.with(scope
, |_
, this
| this
.visit_ty(output
));
2249 debug
!("visit_fn_like_elision: exit");
2251 struct GatherLifetimes
<'a
> {
2252 map
: &'a NamedRegionMap
,
2253 outer_index
: ty
::DebruijnIndex
,
2254 have_bound_regions
: bool
,
2255 lifetimes
: FxHashSet
<Region
>,
2258 impl<'v
, 'a
> Visitor
<'v
> for GatherLifetimes
<'a
> {
2259 type Map
= intravisit
::ErasedMap
<'v
>;
2261 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
2262 NestedVisitorMap
::None
2265 fn visit_ty(&mut self, ty
: &hir
::Ty
<'_
>) {
2266 if let hir
::TyKind
::BareFn(_
) = ty
.kind
{
2267 self.outer_index
.shift_in(1);
2270 hir
::TyKind
::TraitObject(bounds
, ref lifetime
) => {
2271 for bound
in bounds
{
2272 self.visit_poly_trait_ref(bound
, hir
::TraitBoundModifier
::None
);
2275 // Stay on the safe side and don't include the object
2276 // lifetime default (which may not end up being used).
2277 if !lifetime
.is_elided() {
2278 self.visit_lifetime(lifetime
);
2282 intravisit
::walk_ty(self, ty
);
2285 if let hir
::TyKind
::BareFn(_
) = ty
.kind
{
2286 self.outer_index
.shift_out(1);
2290 fn visit_generic_param(&mut self, param
: &hir
::GenericParam
<'_
>) {
2291 if let hir
::GenericParamKind
::Lifetime { .. }
= param
.kind
{
2292 // FIXME(eddyb) Do we want this? It only makes a difference
2293 // if this `for<'a>` lifetime parameter is never used.
2294 self.have_bound_regions
= true;
2297 intravisit
::walk_generic_param(self, param
);
2300 fn visit_poly_trait_ref(
2302 trait_ref
: &hir
::PolyTraitRef
<'_
>,
2303 modifier
: hir
::TraitBoundModifier
,
2305 self.outer_index
.shift_in(1);
2306 intravisit
::walk_poly_trait_ref(self, trait_ref
, modifier
);
2307 self.outer_index
.shift_out(1);
2310 fn visit_lifetime(&mut self, lifetime_ref
: &hir
::Lifetime
) {
2311 if let Some(&lifetime
) = self.map
.defs
.get(&lifetime_ref
.hir_id
) {
2313 Region
::LateBound(debruijn
, _
, _
) | Region
::LateBoundAnon(debruijn
, _
)
2314 if debruijn
< self.outer_index
=>
2316 self.have_bound_regions
= true;
2319 self.lifetimes
.insert(lifetime
.shifted_out_to_binder(self.outer_index
));
2327 fn resolve_elided_lifetimes(&mut self, lifetime_refs
: Vec
<&'tcx hir
::Lifetime
>) {
2328 debug
!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs
);
2330 if lifetime_refs
.is_empty() {
2334 let span
= lifetime_refs
[0].span
;
2335 let mut late_depth
= 0;
2336 let mut scope
= self.scope
;
2337 let mut lifetime_names
= FxHashSet
::default();
2340 // Do not assign any resolution, it will be inferred.
2341 Scope
::Body { .. }
=> return,
2343 Scope
::Root
=> break None
,
2345 Scope
::Binder { s, ref lifetimes, .. }
=> {
2346 // collect named lifetimes for suggestions
2347 for name
in lifetimes
.keys() {
2348 if let hir
::ParamName
::Plain(name
) = name
{
2349 lifetime_names
.insert(*name
);
2356 Scope
::Elision { ref elide, ref s, .. }
=> {
2357 let lifetime
= match *elide
{
2358 Elide
::FreshLateAnon(ref counter
) => {
2359 for lifetime_ref
in lifetime_refs
{
2360 let lifetime
= Region
::late_anon(counter
).shifted(late_depth
);
2361 self.insert_lifetime(lifetime_ref
, lifetime
);
2365 Elide
::Exact(l
) => l
.shifted(late_depth
),
2366 Elide
::Error(ref e
) => {
2367 if let Scope
::Binder { ref lifetimes, .. }
= s
{
2368 // collect named lifetimes for suggestions
2369 for name
in lifetimes
.keys() {
2370 if let hir
::ParamName
::Plain(name
) = name
{
2371 lifetime_names
.insert(*name
);
2378 for lifetime_ref
in lifetime_refs
{
2379 self.insert_lifetime(lifetime_ref
, lifetime
);
2384 Scope
::ObjectLifetimeDefault { s, .. }
=> {
2390 let mut err
= self.report_missing_lifetime_specifiers(span
, lifetime_refs
.len());
2391 let mut add_label
= true;
2393 if let Some(params
) = error
{
2394 if lifetime_refs
.len() == 1 {
2395 add_label
= add_label
&& self.report_elision_failure(&mut err
, params
, span
);
2399 self.add_missing_lifetime_specifiers_label(
2402 lifetime_refs
.len(),
2404 error
.map(|p
| &p
[..]).unwrap_or(&[]),
2411 fn suggest_lifetime(&self, db
: &mut DiagnosticBuilder
<'_
>, span
: Span
, msg
: &str) -> bool
{
2412 match self.tcx
.sess
.source_map().span_to_snippet(span
) {
2413 Ok(ref snippet
) => {
2414 let (sugg
, applicability
) = if snippet
== "&" {
2415 ("&'static ".to_owned(), Applicability
::MachineApplicable
)
2416 } else if snippet
== "'_" {
2417 ("'static".to_owned(), Applicability
::MachineApplicable
)
2419 (format
!("{} + 'static", snippet
), Applicability
::MaybeIncorrect
)
2421 db
.span_suggestion(span
, msg
, sugg
, applicability
);
2431 fn report_elision_failure(
2433 db
: &mut DiagnosticBuilder
<'_
>,
2434 params
: &[ElisionFailureInfo
],
2437 let mut m
= String
::new();
2438 let len
= params
.len();
2440 let elided_params
: Vec
<_
> =
2441 params
.iter().cloned().filter(|info
| info
.lifetime_count
> 0).collect();
2443 let elided_len
= elided_params
.len();
2445 for (i
, info
) in elided_params
.into_iter().enumerate() {
2446 let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span }
=
2449 db
.span_label(span
, "");
2450 let help_name
= if let Some(ident
) =
2451 parent
.and_then(|body
| self.tcx
.hir().body(body
).params
[index
].pat
.simple_ident())
2453 format
!("`{}`", ident
)
2455 format
!("argument {}", index
+ 1)
2463 "one of {}'s {} {}lifetimes",
2466 if have_bound_regions { "free " }
else { "" }
2471 if elided_len
== 2 && i
== 0 {
2473 } else if i
+ 2 == elided_len
{
2474 m
.push_str(", or ");
2475 } else if i
!= elided_len
- 1 {
2482 "this function's return type contains a borrowed value, \
2483 but there is no value for it to be borrowed from",
2485 self.suggest_lifetime(db
, span
, "consider giving it a 'static lifetime")
2486 } else if elided_len
== 0 {
2488 "this function's return type contains a borrowed value with \
2489 an elided lifetime, but the lifetime cannot be derived from \
2492 let msg
= "consider giving it an explicit bounded or 'static lifetime";
2493 self.suggest_lifetime(db
, span
, msg
)
2494 } else if elided_len
== 1 {
2496 "this function's return type contains a borrowed value, \
2497 but the signature does not say which {} it is borrowed from",
2503 "this function's return type contains a borrowed value, \
2504 but the signature does not say whether it is borrowed from {}",
2511 fn resolve_object_lifetime_default(&mut self, lifetime_ref
: &'tcx hir
::Lifetime
) {
2512 debug
!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref
);
2513 let mut late_depth
= 0;
2514 let mut scope
= self.scope
;
2515 let lifetime
= loop {
2517 Scope
::Binder { s, .. }
=> {
2522 Scope
::Root
| Scope
::Elision { .. }
=> break Region
::Static
,
2524 Scope
::Body { .. }
| Scope
::ObjectLifetimeDefault { lifetime: None, .. }
=> return,
2526 Scope
::ObjectLifetimeDefault { lifetime: Some(l), .. }
=> break l
,
2529 self.insert_lifetime(lifetime_ref
, lifetime
.shifted(late_depth
));
2532 fn check_lifetime_params(
2534 old_scope
: ScopeRef
<'_
>,
2535 params
: &'tcx
[hir
::GenericParam
<'tcx
>],
2537 let lifetimes
: Vec
<_
> = params
2539 .filter_map(|param
| match param
.kind
{
2540 GenericParamKind
::Lifetime { .. }
=> {
2541 Some((param
, param
.name
.normalize_to_macros_2_0()))
2546 for (i
, (lifetime_i
, lifetime_i_name
)) in lifetimes
.iter().enumerate() {
2547 if let hir
::ParamName
::Plain(_
) = lifetime_i_name
{
2548 let name
= lifetime_i_name
.ident().name
;
2549 if name
== kw
::UnderscoreLifetime
|| name
== kw
::StaticLifetime
{
2550 let mut err
= struct_span_err
!(
2554 "invalid lifetime parameter name: `{}`",
2555 lifetime_i
.name
.ident(),
2559 format
!("{} is a reserved lifetime name", name
),
2565 // It is a hard error to shadow a lifetime within the same scope.
2566 for (lifetime_j
, lifetime_j_name
) in lifetimes
.iter().skip(i
+ 1) {
2567 if lifetime_i_name
== lifetime_j_name
{
2572 "lifetime name `{}` declared twice in the same scope",
2573 lifetime_j
.name
.ident()
2575 .span_label(lifetime_j
.span
, "declared twice")
2576 .span_label(lifetime_i
.span
, "previous declaration here")
2581 // It is a soft error to shadow a lifetime within a parent scope.
2582 self.check_lifetime_param_for_shadowing(old_scope
, &lifetime_i
);
2584 for bound
in lifetime_i
.bounds
{
2586 hir
::GenericBound
::Outlives(ref lt
) => match lt
.name
{
2587 hir
::LifetimeName
::Underscore
=> self.tcx
.sess
.delay_span_bug(
2589 "use of `'_` in illegal place, but not caught by lowering",
2591 hir
::LifetimeName
::Static
=> {
2592 self.insert_lifetime(lt
, Region
::Static
);
2596 lifetime_i
.span
.to(lt
.span
),
2598 "unnecessary lifetime parameter `{}`",
2599 lifetime_i
.name
.ident(),
2603 "you can use the `'static` lifetime directly, in place of `{}`",
2604 lifetime_i
.name
.ident(),
2608 hir
::LifetimeName
::Param(_
) | hir
::LifetimeName
::Implicit
=> {
2609 self.resolve_lifetime_ref(lt
);
2611 hir
::LifetimeName
::ImplicitObjectLifetimeDefault
=> {
2612 self.tcx
.sess
.delay_span_bug(
2614 "lowering generated `ImplicitObjectLifetimeDefault` \
2615 outside of an object type",
2618 hir
::LifetimeName
::Error
=> {
2619 // No need to do anything, error already reported.
2628 fn check_lifetime_param_for_shadowing(
2630 mut old_scope
: ScopeRef
<'_
>,
2631 param
: &'tcx hir
::GenericParam
<'tcx
>,
2633 for label
in &self.labels_in_fn
{
2634 // FIXME (#24278): non-hygienic comparison
2635 if param
.name
.ident().name
== label
.name
{
2636 signal_shadowing_problem(
2639 original_label(label
.span
),
2640 shadower_lifetime(¶m
),
2648 Scope
::Body { s, .. }
2649 | Scope
::Elision { s, .. }
2650 | Scope
::ObjectLifetimeDefault { s, .. }
=> {
2658 Scope
::Binder { ref lifetimes, s, .. }
=> {
2659 if let Some(&def
) = lifetimes
.get(¶m
.name
.normalize_to_macros_2_0()) {
2660 let hir_id
= self.tcx
.hir().as_local_hir_id(def
.id().unwrap()).unwrap();
2662 signal_shadowing_problem(
2664 param
.name
.ident().name
,
2665 original_lifetime(self.tcx
.hir().span(hir_id
)),
2666 shadower_lifetime(¶m
),
2677 /// Returns `true` if, in the current scope, replacing `'_` would be
2678 /// equivalent to a single-use lifetime.
2679 fn track_lifetime_uses(&self) -> bool
{
2680 let mut scope
= self.scope
;
2683 Scope
::Root
=> break false,
2685 // Inside of items, it depends on the kind of item.
2686 Scope
::Binder { track_lifetime_uses, .. }
=> break track_lifetime_uses
,
2688 // Inside a body, `'_` will use an inference variable,
2690 Scope
::Body { .. }
=> break true,
2692 // A lifetime only used in a fn argument could as well
2693 // be replaced with `'_`, as that would generate a
2695 Scope
::Elision { elide: Elide::FreshLateAnon(_), .. }
=> break true,
2697 // In the return type or other such place, `'_` is not
2698 // going to make a fresh name, so we cannot
2699 // necessarily replace a single-use lifetime with
2701 Scope
::Elision { elide: Elide::Exact(_), .. }
=> break false,
2702 Scope
::Elision { elide: Elide::Error(_), .. }
=> break false,
2704 Scope
::ObjectLifetimeDefault { s, .. }
=> scope
= s
,
2709 fn insert_lifetime(&mut self, lifetime_ref
: &'tcx hir
::Lifetime
, def
: Region
) {
2711 "insert_lifetime: {} resolved to {:?} span={:?}",
2712 self.tcx
.hir().node_to_string(lifetime_ref
.hir_id
),
2714 self.tcx
.sess
.source_map().span_to_string(lifetime_ref
.span
)
2716 self.map
.defs
.insert(lifetime_ref
.hir_id
, def
);
2719 Region
::LateBoundAnon(..) | Region
::Static
=> {
2720 // These are anonymous lifetimes or lifetimes that are not declared.
2723 Region
::Free(_
, def_id
)
2724 | Region
::LateBound(_
, def_id
, _
)
2725 | Region
::EarlyBound(_
, def_id
, _
) => {
2726 // A lifetime declared by the user.
2727 let track_lifetime_uses
= self.track_lifetime_uses();
2728 debug
!("insert_lifetime: track_lifetime_uses={}", track_lifetime_uses
);
2729 if track_lifetime_uses
&& !self.lifetime_uses
.contains_key(&def_id
) {
2730 debug
!("insert_lifetime: first use of {:?}", def_id
);
2731 self.lifetime_uses
.insert(def_id
, LifetimeUseSet
::One(lifetime_ref
));
2733 debug
!("insert_lifetime: many uses of {:?}", def_id
);
2734 self.lifetime_uses
.insert(def_id
, LifetimeUseSet
::Many
);
2740 /// Sometimes we resolve a lifetime, but later find that it is an
2741 /// error (esp. around impl trait). In that case, we remove the
2742 /// entry into `map.defs` so as not to confuse later code.
2743 fn uninsert_lifetime_on_error(&mut self, lifetime_ref
: &'tcx hir
::Lifetime
, bad_def
: Region
) {
2744 let old_value
= self.map
.defs
.remove(&lifetime_ref
.hir_id
);
2745 assert_eq
!(old_value
, Some(bad_def
));
2749 /// Detects late-bound lifetimes and inserts them into
2750 /// `map.late_bound`.
2752 /// A region declared on a fn is **late-bound** if:
2753 /// - it is constrained by an argument type;
2754 /// - it does not appear in a where-clause.
2756 /// "Constrained" basically means that it appears in any type but
2757 /// not amongst the inputs to a projection. In other words, `<&'a
2758 /// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
2759 fn insert_late_bound_lifetimes(
2760 map
: &mut NamedRegionMap
,
2761 decl
: &hir
::FnDecl
<'_
>,
2762 generics
: &hir
::Generics
<'_
>,
2764 debug
!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl
, generics
);
2766 let mut constrained_by_input
= ConstrainedCollector
::default();
2767 for arg_ty
in decl
.inputs
{
2768 constrained_by_input
.visit_ty(arg_ty
);
2771 let mut appears_in_output
= AllCollector
::default();
2772 intravisit
::walk_fn_ret_ty(&mut appears_in_output
, &decl
.output
);
2774 debug
!("insert_late_bound_lifetimes: constrained_by_input={:?}", constrained_by_input
.regions
);
2776 // Walk the lifetimes that appear in where clauses.
2778 // Subtle point: because we disallow nested bindings, we can just
2779 // ignore binders here and scrape up all names we see.
2780 let mut appears_in_where_clause
= AllCollector
::default();
2781 appears_in_where_clause
.visit_generics(generics
);
2783 for param
in generics
.params
{
2784 if let hir
::GenericParamKind
::Lifetime { .. }
= param
.kind
{
2785 if !param
.bounds
.is_empty() {
2786 // `'a: 'b` means both `'a` and `'b` are referenced
2787 appears_in_where_clause
2789 .insert(hir
::LifetimeName
::Param(param
.name
.normalize_to_macros_2_0()));
2795 "insert_late_bound_lifetimes: appears_in_where_clause={:?}",
2796 appears_in_where_clause
.regions
2799 // Late bound regions are those that:
2800 // - appear in the inputs
2801 // - do not appear in the where-clauses
2802 // - are not implicitly captured by `impl Trait`
2803 for param
in generics
.params
{
2805 hir
::GenericParamKind
::Lifetime { .. }
=> { /* fall through */ }
2807 // Neither types nor consts are late-bound.
2808 hir
::GenericParamKind
::Type { .. }
| hir
::GenericParamKind
::Const { .. }
=> continue,
2811 let lt_name
= hir
::LifetimeName
::Param(param
.name
.normalize_to_macros_2_0());
2812 // appears in the where clauses? early-bound.
2813 if appears_in_where_clause
.regions
.contains(<_name
) {
2817 // does not appear in the inputs, but appears in the return type? early-bound.
2818 if !constrained_by_input
.regions
.contains(<_name
)
2819 && appears_in_output
.regions
.contains(<_name
)
2825 "insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound",
2830 let inserted
= map
.late_bound
.insert(param
.hir_id
);
2831 assert
!(inserted
, "visited lifetime {:?} twice", param
.hir_id
);
2837 struct ConstrainedCollector
{
2838 regions
: FxHashSet
<hir
::LifetimeName
>,
2841 impl<'v
> Visitor
<'v
> for ConstrainedCollector
{
2842 type Map
= intravisit
::ErasedMap
<'v
>;
2844 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
2845 NestedVisitorMap
::None
2848 fn visit_ty(&mut self, ty
: &'v hir
::Ty
<'v
>) {
2851 hir
::QPath
::Resolved(Some(_
), _
) | hir
::QPath
::TypeRelative(..),
2853 // ignore lifetimes appearing in associated type
2854 // projections, as they are not *constrained*
2858 hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) => {
2859 // consider only the lifetimes on the final
2860 // segment; I am not sure it's even currently
2861 // valid to have them elsewhere, but even if it
2862 // is, those would be potentially inputs to
2864 if let Some(last_segment
) = path
.segments
.last() {
2865 self.visit_path_segment(path
.span
, last_segment
);
2870 intravisit
::walk_ty(self, ty
);
2875 fn visit_lifetime(&mut self, lifetime_ref
: &'v hir
::Lifetime
) {
2876 self.regions
.insert(lifetime_ref
.name
.normalize_to_macros_2_0());
2881 struct AllCollector
{
2882 regions
: FxHashSet
<hir
::LifetimeName
>,
2885 impl<'v
> Visitor
<'v
> for AllCollector
{
2886 type Map
= intravisit
::ErasedMap
<'v
>;
2888 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
2889 NestedVisitorMap
::None
2892 fn visit_lifetime(&mut self, lifetime_ref
: &'v hir
::Lifetime
) {
2893 self.regions
.insert(lifetime_ref
.name
.normalize_to_macros_2_0());