@@ -1557,14 +1557,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
15571557 if ident.name == kw::StaticLifetime {
15581558 self.record_lifetime_res(
15591559 lifetime.id,
1560- LifetimeRes :: Static ,
1560+ LifetimeRes::Static { suppress_elision_warning: false } ,
15611561 LifetimeElisionCandidate::Named,
15621562 );
15631563 return;
15641564 }
15651565
15661566 if ident.name == kw::UnderscoreLifetime {
1567- return self . resolve_anonymous_lifetime ( lifetime, false ) ;
1567+ return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false);
15681568 }
15691569
15701570 let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
@@ -1667,13 +1667,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
16671667 }
16681668
16691669 #[instrument(level = "debug", skip(self))]
1670- fn resolve_anonymous_lifetime ( & mut self , lifetime : & Lifetime , elided : bool ) {
1670+ fn resolve_anonymous_lifetime(
1671+ &mut self,
1672+ lifetime: &Lifetime,
1673+ id_for_lint: NodeId,
1674+ elided: bool,
1675+ ) {
16711676 debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
16721677
16731678 let kind =
16741679 if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore };
1675- let missing_lifetime =
1676- MissingLifetime { id : lifetime. id , span : lifetime. ident . span , kind, count : 1 } ;
1680+ let missing_lifetime = MissingLifetime {
1681+ id: lifetime.id,
1682+ span: lifetime.ident.span,
1683+ kind,
1684+ count: 1,
1685+ id_for_lint,
1686+ };
16771687 let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
16781688 for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
16791689 debug!(?rib.kind);
@@ -1697,7 +1707,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
16971707 if lifetimes_in_scope.is_empty() {
16981708 self.record_lifetime_res(
16991709 lifetime.id,
1700- LifetimeRes :: Static ,
1710+ // We are inside a const item, so do not warn.
1711+ LifetimeRes::Static { suppress_elision_warning: true },
17011712 elision_candidate,
17021713 );
17031714 return;
@@ -1800,7 +1811,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
18001811 LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
18011812 LifetimeElisionCandidate::Ignore,
18021813 );
1803- self . resolve_anonymous_lifetime ( & lt, true ) ;
1814+ self.resolve_anonymous_lifetime(<, anchor_id, true);
18041815 }
18051816
18061817 #[instrument(level = "debug", skip(self))]
@@ -1916,6 +1927,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
19161927 };
19171928 let missing_lifetime = MissingLifetime {
19181929 id: node_ids.start,
1930+ id_for_lint: segment_id,
19191931 span: elided_lifetime_span,
19201932 kind,
19211933 count: expected_lifetimes,
@@ -2039,8 +2051,44 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
20392051 if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
20402052 panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)")
20412053 }
2054+
2055+ match candidate {
2056+ LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => {
2057+ debug_assert_eq!(id, missing.id);
2058+ match res {
2059+ LifetimeRes::Static { suppress_elision_warning } => {
2060+ if !suppress_elision_warning {
2061+ self.r.lint_buffer.buffer_lint(
2062+ lint::builtin::ELIDED_NAMED_LIFETIMES,
2063+ missing.id_for_lint,
2064+ missing.span,
2065+ BuiltinLintDiag::ElidedIsStatic { elided: missing.span },
2066+ );
2067+ }
2068+ }
2069+ LifetimeRes::Param { param, binder: _ } => {
2070+ let tcx = self.r.tcx();
2071+ self.r.lint_buffer.buffer_lint(
2072+ lint::builtin::ELIDED_NAMED_LIFETIMES,
2073+ missing.id_for_lint,
2074+ missing.span,
2075+ BuiltinLintDiag::ElidedIsParam {
2076+ elided: missing.span,
2077+ param: (tcx.item_name(param.into()), tcx.source_span(param)),
2078+ },
2079+ );
2080+ }
2081+ LifetimeRes::Fresh { .. }
2082+ | LifetimeRes::Infer
2083+ | LifetimeRes::Error
2084+ | LifetimeRes::ElidedAnchor { .. } => {}
2085+ }
2086+ }
2087+ LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {}
2088+ }
2089+
20422090 match res {
2043- LifetimeRes :: Param { .. } | LifetimeRes :: Fresh { .. } | LifetimeRes :: Static => {
2091+ LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => {
20442092 if let Some(ref mut candidates) = self.lifetime_elision_candidates {
20452093 candidates.push((res, candidate));
20462094 }
@@ -2558,9 +2606,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
25582606
25592607 ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
25602608 self.with_static_rib(def_kind, |this| {
2561- this. with_lifetime_rib ( LifetimeRibKind :: Elided ( LifetimeRes :: Static ) , |this| {
2562- this. visit_ty ( ty) ;
2563- } ) ;
2609+ this.with_lifetime_rib(
2610+ LifetimeRibKind::Elided(LifetimeRes::Static {
2611+ suppress_elision_warning: true,
2612+ }),
2613+ |this| {
2614+ this.visit_ty(ty);
2615+ },
2616+ );
25642617 if let Some(expr) = expr {
25652618 // We already forbid generic params because of the above item rib,
25662619 // so it doesn't matter whether this is a trivial constant.
@@ -2589,7 +2642,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
25892642 this.visit_generics(generics);
25902643
25912644 this.with_lifetime_rib(
2592- LifetimeRibKind :: Elided ( LifetimeRes :: Static ) ,
2645+ LifetimeRibKind::Elided(LifetimeRes::Static {
2646+ suppress_elision_warning: true,
2647+ }),
25932648 |this| this.visit_ty(ty),
25942649 );
25952650
0 commit comments