From 23cf5dd9cf32f4df511b96eaec1c8565128fa804 Mon Sep 17 00:00:00 2001 From: Jeremy Davis 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 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 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 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 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| {