Skip to content

Commit dec4f33

Browse files
committed
Add lint for statics with explicit static lifetime.
1 parent f3087c3 commit dec4f33

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

clippy_lints/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ pub mod returns;
255255
pub mod serde_api;
256256
pub mod shadow;
257257
pub mod slow_vector_initialization;
258+
pub mod static_static_lifetime;
258259
pub mod strings;
259260
pub mod suspicious_trait_impl;
260261
pub mod swap;
@@ -552,6 +553,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
552553
reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default());
553554
reg.register_late_lint_pass(box types::ImplicitHasher);
554555
reg.register_early_lint_pass(box const_static_lifetime::StaticConst);
556+
reg.register_early_lint_pass(box static_static_lifetime::StaticStatic);
555557
reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom);
556558
reg.register_late_lint_pass(box replace_consts::ReplaceConsts);
557559
reg.register_late_lint_pass(box types::UnitArg);
@@ -682,6 +684,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
682684
cognitive_complexity::COGNITIVE_COMPLEXITY,
683685
collapsible_if::COLLAPSIBLE_IF,
684686
const_static_lifetime::CONST_STATIC_LIFETIME,
687+
static_static_lifetime::STATIC_STATIC_LIFETIME,
685688
copies::IFS_SAME_COND,
686689
copies::IF_SAME_THEN_ELSE,
687690
derive::DERIVE_HASH_XOR_EQ,
@@ -897,6 +900,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
897900
block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT,
898901
collapsible_if::COLLAPSIBLE_IF,
899902
const_static_lifetime::CONST_STATIC_LIFETIME,
903+
static_static_lifetime::STATIC_STATIC_LIFETIME,
900904
enum_variants::ENUM_VARIANT_NAMES,
901905
enum_variants::MODULE_INCEPTION,
902906
eq_op::OP_REF,
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use crate::utils::{in_macro_or_desugar, snippet, span_lint_and_then};
2+
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
3+
use rustc::{declare_lint_pass, declare_tool_lint};
4+
use rustc_errors::Applicability;
5+
use syntax::ast::*;
6+
7+
declare_clippy_lint! {
8+
/// **What it does:** Checks for statics with an explicit `'static` lifetime.
9+
///
10+
/// **Why is this bad?** Adding `'static` to every reference can create very
11+
/// complicated types.
12+
///
13+
/// **Known problems:** None.
14+
///
15+
/// **Example:**
16+
/// ```ignore
17+
/// static FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
18+
/// &[...]
19+
/// ```
20+
/// This code can be rewritten as
21+
/// ```ignore
22+
/// static FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
23+
/// ```
24+
pub STATIC_STATIC_LIFETIME,
25+
style,
26+
"Using explicit `'static` lifetime for statics when elision rules would allow omitting them."
27+
}
28+
29+
declare_lint_pass!(StaticStatic => [STATIC_STATIC_LIFETIME]);
30+
31+
impl StaticStatic {
32+
// Recursively visit types
33+
fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>) {
34+
match ty.node {
35+
// Be careful of nested structures (arrays and tuples)
36+
TyKind::Array(ref ty, _) => {
37+
self.visit_type(&*ty, cx);
38+
},
39+
TyKind::Tup(ref tup) => {
40+
for tup_ty in tup {
41+
self.visit_type(&*tup_ty, cx);
42+
}
43+
},
44+
// This is what we are looking for !
45+
TyKind::Rptr(ref optional_lifetime, ref borrow_type) => {
46+
// Match the 'static lifetime
47+
if let Some(lifetime) = *optional_lifetime {
48+
match borrow_type.ty.node {
49+
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
50+
if lifetime.ident.name == syntax::symbol::kw::StaticLifetime {
51+
let snip = snippet(cx, borrow_type.ty.span, "<type>");
52+
let sugg = format!("&{}", snip);
53+
span_lint_and_then(
54+
cx,
55+
STATIC_STATIC_LIFETIME,
56+
lifetime.ident.span,
57+
"Statics have by default a `'static` lifetime",
58+
|db| {
59+
db.span_suggestion(
60+
ty.span,
61+
"consider removing `'static`",
62+
sugg,
63+
Applicability::MachineApplicable, //snippet
64+
);
65+
},
66+
);
67+
}
68+
},
69+
_ => {},
70+
}
71+
}
72+
self.visit_type(&*borrow_type.ty, cx);
73+
},
74+
TyKind::Slice(ref ty) => {
75+
self.visit_type(ty, cx);
76+
},
77+
_ => {},
78+
}
79+
}
80+
}
81+
82+
impl EarlyLintPass for StaticStatic {
83+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
84+
if !in_macro_or_desugar(item.span) {
85+
// Match only statics...
86+
if let ItemKind::Static(ref var_type, _, _) = item.node {
87+
self.visit_type(var_type, cx);
88+
}
89+
}
90+
}
91+
92+
// Don't check associated consts because `'static` cannot be elided on those (issue #2438)
93+
}

tests/ui/static_static_lifetime.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#[derive(Debug)]
2+
struct Foo {}
3+
4+
static VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static.
5+
6+
static VAR_TWO: &str = "Test static #2"; // This line should not raise a warning.
7+
8+
static VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
9+
10+
static VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
11+
12+
static VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
13+
14+
static VAR_SIX: &'static u8 = &5;
15+
16+
static VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
17+
18+
static VAR_HEIGHT: &'static Foo = &Foo {};
19+
20+
static VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static.
21+
22+
static VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
23+
24+
static VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
25+
26+
fn main() {
27+
let false_positive: &'static str = "test";
28+
println!("{}", VAR_ONE);
29+
println!("{}", VAR_TWO);
30+
println!("{:?}", VAR_THREE);
31+
println!("{:?}", VAR_FOUR);
32+
println!("{:?}", VAR_FIVE);
33+
println!("{:?}", VAR_SIX);
34+
println!("{:?}", VAR_SEVEN);
35+
println!("{:?}", VAR_HEIGHT);
36+
println!("{}", false_positive);
37+
}
38+
39+
// trait Bar {
40+
// static TRAIT_VAR: &'static str;
41+
// }
42+
43+
// impl Foo {
44+
// static IMPL_VAR: &'static str = "var";
45+
// }
46+
47+
// impl Bar for Foo {
48+
// static TRAIT_VAR: &'static str = "foo";
49+
// }
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
error: Statics have by default a `'static` lifetime
2+
--> $DIR/static_static_lifetime.rs:4:18
3+
|
4+
LL | static VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static.
5+
| -^^^^^^^---- help: consider removing `'static`: `&str`
6+
|
7+
= note: `-D clippy::static-static-lifetime` implied by `-D warnings`
8+
9+
error: Statics have by default a `'static` lifetime
10+
--> $DIR/static_static_lifetime.rs:8:22
11+
|
12+
LL | static VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
13+
| -^^^^^^^---- help: consider removing `'static`: `&str`
14+
15+
error: Statics have by default a `'static` lifetime
16+
--> $DIR/static_static_lifetime.rs:10:33
17+
|
18+
LL | static VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
19+
| -^^^^^^^---- help: consider removing `'static`: `&str`
20+
21+
error: Statics have by default a `'static` lifetime
22+
--> $DIR/static_static_lifetime.rs:10:48
23+
|
24+
LL | static VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
25+
| -^^^^^^^---- help: consider removing `'static`: `&str`
26+
27+
error: Statics have by default a `'static` lifetime
28+
--> $DIR/static_static_lifetime.rs:12:19
29+
|
30+
LL | static VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
31+
| -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]`
32+
33+
error: Statics have by default a `'static` lifetime
34+
--> $DIR/static_static_lifetime.rs:12:31
35+
|
36+
LL | static VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
37+
| -^^^^^^^---- help: consider removing `'static`: `&str`
38+
39+
error: Statics have by default a `'static` lifetime
40+
--> $DIR/static_static_lifetime.rs:14:18
41+
|
42+
LL | static VAR_SIX: &'static u8 = &5;
43+
| -^^^^^^^--- help: consider removing `'static`: `&u8`
44+
45+
error: Statics have by default a `'static` lifetime
46+
--> $DIR/static_static_lifetime.rs:16:30
47+
|
48+
LL | static VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
49+
| -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]`
50+
51+
error: Statics have by default a `'static` lifetime
52+
--> $DIR/static_static_lifetime.rs:16:40
53+
|
54+
LL | static VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
55+
| -^^^^^^^---- help: consider removing `'static`: `&str`
56+
57+
error: Statics have by default a `'static` lifetime
58+
--> $DIR/static_static_lifetime.rs:18:21
59+
|
60+
LL | static VAR_HEIGHT: &'static Foo = &Foo {};
61+
| -^^^^^^^---- help: consider removing `'static`: `&Foo`
62+
63+
error: Statics have by default a `'static` lifetime
64+
--> $DIR/static_static_lifetime.rs:20:20
65+
|
66+
LL | static VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static.
67+
| -^^^^^^^----- help: consider removing `'static`: `&[u8]`
68+
69+
error: Statics have by default a `'static` lifetime
70+
--> $DIR/static_static_lifetime.rs:22:20
71+
|
72+
LL | static VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
73+
| -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
74+
75+
error: Statics have by default a `'static` lifetime
76+
--> $DIR/static_static_lifetime.rs:24:20
77+
|
78+
LL | static VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
79+
| -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
80+
81+
error: aborting due to 13 previous errors
82+

0 commit comments

Comments
 (0)