From 23cf5dd9cf32f4df511b96eaec1c8565128fa804 Mon Sep 17 00:00:00 2001
From: Jeremy Davis <jeremydavis519@gmail.com>
Date: Mon, 13 Jun 2022 19:43:34 -0500
Subject: [PATCH 1/4] Define the `named_static_lifetimes` lint

This lint will replace the existing hard-warning.
---
 compiler/rustc_lint_defs/src/builtin.rs | 35 +++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index a067534b18938..2baaad0c642f6 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1621,6 +1621,40 @@ declare_lint! {
     "detects lifetime parameters that are never used"
 }
 
+declare_lint! {
+    /// The `named_static_lifetimes` lint detects lifetime parameters that are
+    /// defined as outliving the static lifetime.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #[deny(named_static_lifetimes)]
+    ///
+    /// pub fn foo<'a>(_s: &'a str) where 'a: 'static {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// By definition, the static lifetime (`'static`) outlives every other
+    /// lifetime. If another lifetime `'a` lives at least as long as `'static`,
+    /// then it is identical to `'static`. In that case, there is no need for
+    /// the name `'a`, and it likely only makes the code harder to read.
+    ///
+    /// To fix this, consider using `'static` instead of the named lifetime.
+    /// Here is the result of doing that in the example above:
+    ///
+    /// ```rust
+    /// #[deny(named_static_lifetimes)]
+    ///
+    /// pub fn foo(_s: &'static str) {}
+    /// ```
+    pub NAMED_STATIC_LIFETIMES,
+    Warn,
+    "detects lifetime parameters that are identical to `'static`"
+}
+
 declare_lint! {
     /// The `tyvar_behind_raw_pointer` lint detects raw pointer to an
     /// inference variable.
@@ -3174,6 +3208,7 @@ declare_lint_pass! {
         UNCONDITIONAL_RECURSION,
         SINGLE_USE_LIFETIMES,
         UNUSED_LIFETIMES,
+        NAMED_STATIC_LIFETIMES,
         UNUSED_LABELS,
         TYVAR_BEHIND_RAW_POINTER,
         ELIDED_LIFETIMES_IN_PATHS,

From cc9f4c2debc85f14f27d8514aa8ed2ec7d9467dd Mon Sep 17 00:00:00 2001
From: Jeremy Davis <jeremydavis519@gmail.com>
Date: Mon, 13 Jun 2022 20:41:48 -0500
Subject: [PATCH 2/4] Replace the named static lifetime hard-warning with the
 new lint

---
 Cargo.lock                                   |  1 +
 compiler/rustc_resolve/Cargo.toml            |  1 +
 compiler/rustc_resolve/src/late/lifetimes.rs | 29 ++++++++++++--------
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 51b0da65b3145..33d0973ab5d54 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4380,6 +4380,7 @@ dependencies = [
  "rustc_feature",
  "rustc_hir",
  "rustc_index",
+ "rustc_lint_defs",
  "rustc_metadata",
  "rustc_middle",
  "rustc_query_system",
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index b2178ff59954b..33436c6ee83d2 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -21,6 +21,7 @@ rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
+rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_metadata = { path = "../rustc_metadata" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 447f4174c10d5..e5c565e4f96c9 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -16,6 +16,7 @@ use rustc_hir::def_id::{DefIdMap, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
 use rustc_hir::{GenericParamKind, HirIdMap};
+use rustc_lint_defs::builtin::NAMED_STATIC_LIFETIMES;
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_lifetime::*;
@@ -1255,20 +1256,24 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                     continue;
                                 }
                                 this.insert_lifetime(lt, Region::Static);
-                                this.tcx
-                                    .sess
-                                    .struct_span_warn(
-                                        lifetime.span,
-                                        &format!(
+                                this.tcx.struct_span_lint_hir(
+                                    NAMED_STATIC_LIFETIMES,
+                                    lifetime.hir_id,
+                                    lifetime.span,
+                                    |lint| {
+                                        let msg = &format!(
                                             "unnecessary lifetime parameter `{}`",
                                             lifetime.name.ident(),
-                                        ),
-                                    )
-                                    .help(&format!(
-                                        "you can use the `'static` lifetime directly, in place of `{}`",
-                                        lifetime.name.ident(),
-                                    ))
-                                    .emit();
+                                        );
+                                        let help = &format!(
+                                            "you can use the `'static` lifetime directly, in place of `{}`",
+                                            lifetime.name.ident(),
+                                        );
+                                        lint.build(msg)
+                                            .help(help)
+                                            .emit();
+                                    },
+                                );
                             }
                         }
                     }

From 47ed1a3d61a62124937e14720d4c46c8ca28a725 Mon Sep 17 00:00:00 2001
From: Jeremy Davis <jeremydavis519@gmail.com>
Date: Mon, 13 Jun 2022 23:36:01 -0500
Subject: [PATCH 3/4] Update the UI tests for the `named_static_lifetimes` lint

---
 .../unsatified-item-lifetime-bound.stderr                        | 1 +
 src/test/ui/impl-trait/equal-hidden-lifetimes.stderr             | 1 +
 src/test/ui/issues/issue-30438-c.stderr                          | 1 +
 ...gions-free-region-outlives-static-outlives-free-region.stderr | 1 +
 src/test/ui/regions/regions-static-bound-rpass.stderr            | 1 +
 src/test/ui/regions/regions-static-bound.stderr                  | 1 +
 src/test/ui/static/static-lifetime-bound.stderr                  | 1 +
 src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr      | 1 +
 8 files changed, 8 insertions(+)

diff --git a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr
index ae52010cc50a2..1b600913d6445 100644
--- a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr
+++ b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL |     type Y<'a: 'static>;
    |            ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 error[E0478]: lifetime bound not satisfied
diff --git a/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr b/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr
index 3e48aef553b16..2a3c9f270888f 100644
--- a/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr
+++ b/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
    |                         ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 warning: 1 warning emitted
diff --git a/src/test/ui/issues/issue-30438-c.stderr b/src/test/ui/issues/issue-30438-c.stderr
index a7a5c0500fd23..d06d740ccc709 100644
--- a/src/test/ui/issues/issue-30438-c.stderr
+++ b/src/test/ui/issues/issue-30438-c.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'z`
 LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
    |                                                                          ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'z`
 
 error[E0515]: cannot return reference to local variable `x`
diff --git a/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr b/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
index 70ed418d5cbbb..94d85913c56a9 100644
--- a/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
+++ b/src/test/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL |     where 'a: 'static
    |           ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 warning: 1 warning emitted
diff --git a/src/test/ui/regions/regions-static-bound-rpass.stderr b/src/test/ui/regions/regions-static-bound-rpass.stderr
index 9355a409d5099..298c4ce8b8fbe 100644
--- a/src/test/ui/regions/regions-static-bound-rpass.stderr
+++ b/src/test/ui/regions/regions-static-bound-rpass.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL |     where 'a: 'static { t }
    |           ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 warning: unnecessary lifetime parameter `'a`
diff --git a/src/test/ui/regions/regions-static-bound.stderr b/src/test/ui/regions/regions-static-bound.stderr
index 2886ec3ead51f..678f55e08fadc 100644
--- a/src/test/ui/regions/regions-static-bound.stderr
+++ b/src/test/ui/regions/regions-static-bound.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL |     where 'a: 'static { t }
    |           ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 warning: unnecessary lifetime parameter `'b`
diff --git a/src/test/ui/static/static-lifetime-bound.stderr b/src/test/ui/static/static-lifetime-bound.stderr
index ef07a89315f40..cc7d9b14b4f2f 100644
--- a/src/test/ui/static/static-lifetime-bound.stderr
+++ b/src/test/ui/static/static-lifetime-bound.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL | fn f<'a: 'static>(_: &'a i32) {}
    |      ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 error[E0597]: `x` does not live long enough
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
index 920eef11da4b9..79ad389c03b75 100644
--- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
+++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
@@ -4,6 +4,7 @@ warning: unnecessary lifetime parameter `'a`
 LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
    |      ^^
    |
+   = note: `#[warn(named_static_lifetimes)]` on by default
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
 error: non-defining opaque type use in defining scope

From 897f4d5ccee64f177ff39b781546907697f265ef Mon Sep 17 00:00:00 2001
From: Jeremy Davis <jeremydavis519@gmail.com>
Date: Tue, 14 Jun 2022 09:45:06 -0500
Subject: [PATCH 4/4] Remove the direct dependency on `rustc_lint_defs`

---
 Cargo.lock                                   | 1 -
 compiler/rustc_resolve/Cargo.toml            | 1 -
 compiler/rustc_resolve/src/late/lifetimes.rs | 4 ++--
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 33d0973ab5d54..51b0da65b3145 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4380,7 +4380,6 @@ dependencies = [
  "rustc_feature",
  "rustc_hir",
  "rustc_index",
- "rustc_lint_defs",
  "rustc_metadata",
  "rustc_middle",
  "rustc_query_system",
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 33436c6ee83d2..b2178ff59954b 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -21,7 +21,6 @@ rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
-rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_metadata = { path = "../rustc_metadata" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index e5c565e4f96c9..87898ca4ee897 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -16,12 +16,12 @@ use rustc_hir::def_id::{DefIdMap, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node};
 use rustc_hir::{GenericParamKind, HirIdMap};
-use rustc_lint_defs::builtin::NAMED_STATIC_LIFETIMES;
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_lifetime::*;
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_middle::{bug, span_bug};
+use rustc_session::lint;
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
@@ -1257,7 +1257,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                 }
                                 this.insert_lifetime(lt, Region::Static);
                                 this.tcx.struct_span_lint_hir(
-                                    NAMED_STATIC_LIFETIMES,
+                                    lint::builtin::NAMED_STATIC_LIFETIMES,
                                     lifetime.hir_id,
                                     lifetime.span,
                                     |lint| {