Skip to content

Commit f03e12b

Browse files
authored
Merge pull request #2151 from gbip/master
Implementation of the `const_static_lifetime` lint.
2 parents ebdefff + 625aae7 commit f03e12b

15 files changed

+274
-106
lines changed

clippy_lints/src/approx_const.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ declare_lint! {
3333
}
3434

3535
// Tuples are of the form (constant, name, min_digits)
36-
const KNOWN_CONSTS: &'static [(f64, &'static str, usize)] = &[
36+
const KNOWN_CONSTS: &[(f64, &str, usize)] = &[
3737
(f64::E, "E", 4),
3838
(f64::FRAC_1_PI, "FRAC_1_PI", 4),
3939
(f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5),

clippy_lints/src/block_in_if_condition.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
7171
}
7272
}
7373

74-
const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition";
75-
const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; \
74+
const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition";
75+
const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks or closures with blocks; \
7676
instead, move the block or closure higher and bind it with a 'let'";
7777

7878
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use syntax::ast::{Item, ItemKind, TyKind, Ty};
2+
use rustc::lint::{LintPass, EarlyLintPass, LintArray, EarlyContext};
3+
use utils::{span_lint_and_then, in_macro};
4+
5+
/// **What it does:** Checks for constants with an explicit `'static` lifetime.
6+
///
7+
/// **Why is this bad?** Adding `'static` to every reference can create very
8+
/// complicated types.
9+
///
10+
/// **Known problems:** None.
11+
///
12+
/// **Example:**
13+
/// ```rust
14+
/// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
15+
/// &[...]
16+
/// ```
17+
/// This code can be rewritten as
18+
/// ```rust
19+
/// const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
20+
/// ```
21+
22+
declare_lint! {
23+
pub CONST_STATIC_LIFETIME,
24+
Warn,
25+
"Using explicit `'static` lifetime for constants when elision rules would allow omitting them."
26+
}
27+
28+
pub struct StaticConst;
29+
30+
impl LintPass for StaticConst {
31+
fn get_lints(&self) -> LintArray {
32+
lint_array!(CONST_STATIC_LIFETIME)
33+
}
34+
}
35+
36+
impl StaticConst {
37+
// Recursively visit types
38+
fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext) {
39+
match ty.node {
40+
// Be carefull of nested structures (arrays and tuples)
41+
TyKind::Array(ref ty, _) => {
42+
self.visit_type(&*ty, cx);
43+
},
44+
TyKind::Tup(ref tup) => {
45+
for tup_ty in tup {
46+
self.visit_type(&*tup_ty, cx);
47+
}
48+
},
49+
// This is what we are looking for !
50+
TyKind::Rptr(ref optional_lifetime, ref borrow_type) => {
51+
// Match the 'static lifetime
52+
if let Some(lifetime) = *optional_lifetime {
53+
if let TyKind::Path(_, _) = borrow_type.ty.node {
54+
// Verify that the path is a str
55+
if lifetime.ident.name == "'static" {
56+
let mut sug: String = String::new();
57+
span_lint_and_then(cx,
58+
CONST_STATIC_LIFETIME,
59+
lifetime.span,
60+
"Constants have by default a `'static` lifetime",
61+
|db| {db.span_suggestion(lifetime.span,"consider removing `'static`",sug);});
62+
}
63+
}
64+
}
65+
self.visit_type(&*borrow_type.ty, cx);
66+
},
67+
TyKind::Slice(ref ty) => {
68+
self.visit_type(ty, cx);
69+
},
70+
_ => {},
71+
}
72+
}
73+
}
74+
75+
impl EarlyLintPass for StaticConst {
76+
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
77+
if !in_macro(item.span) {
78+
// Match only constants...
79+
if let ItemKind::Const(ref var_type, _) = item.node {
80+
self.visit_type(var_type, cx);
81+
}
82+
}
83+
}
84+
}

clippy_lints/src/doc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl<'a> Iterator for Parser<'a> {
8888
#[allow(cast_possible_truncation)]
8989
pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(usize, Span)>) {
9090
// one-line comments lose their prefix
91-
const ONELINERS: &'static [&'static str] = &["///!", "///", "//!", "//"];
91+
const ONELINERS: &[&str] = &["///!", "///", "//!", "//"];
9292
for prefix in ONELINERS {
9393
if comment.starts_with(*prefix) {
9494
let doc = &comment[prefix.len()..];

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub mod block_in_if_condition;
7676
pub mod booleans;
7777
pub mod bytecount;
7878
pub mod collapsible_if;
79+
pub mod const_static_lifetime;
7980
pub mod copies;
8081
pub mod cyclomatic_complexity;
8182
pub mod derive;
@@ -339,6 +340,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
339340
reg.register_late_lint_pass(box invalid_ref::InvalidRef);
340341
reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default());
341342
reg.register_late_lint_pass(box types::ImplicitHasher);
343+
reg.register_early_lint_pass(box const_static_lifetime::StaticConst);
342344

343345
reg.register_lint_group("clippy_restrictions", vec![
344346
arithmetic::FLOAT_ARITHMETIC,
@@ -349,6 +351,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
349351

350352
reg.register_lint_group("clippy_pedantic", vec![
351353
booleans::NONMINIMAL_BOOL,
354+
const_static_lifetime::CONST_STATIC_LIFETIME,
352355
empty_enum::EMPTY_ENUM,
353356
enum_glob_use::ENUM_GLOB_USE,
354357
enum_variants::PUB_ENUM_VARIANT_NAMES,

clippy_lints/src/methods.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,7 @@ enum Convention {
15311531
}
15321532

15331533
#[cfg_attr(rustfmt, rustfmt_skip)]
1534-
const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [
1534+
const CONVENTIONS: [(Convention, &[SelfKind]); 6] = [
15351535
(Convention::Eq("new"), &[SelfKind::No]),
15361536
(Convention::StartsWith("as_"), &[SelfKind::Ref, SelfKind::RefMut]),
15371537
(Convention::StartsWith("from_"), &[SelfKind::No]),
@@ -1541,7 +1541,7 @@ const CONVENTIONS: [(Convention, &'static [SelfKind]); 6] = [
15411541
];
15421542

15431543
#[cfg_attr(rustfmt, rustfmt_skip)]
1544-
const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [
1544+
const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [
15451545
("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"),
15461546
("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"),
15471547
("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"),
@@ -1575,7 +1575,7 @@ const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30
15751575
];
15761576

15771577
#[cfg_attr(rustfmt, rustfmt_skip)]
1578-
const PATTERN_METHODS: [(&'static str, usize); 17] = [
1578+
const PATTERN_METHODS: [(&str, usize); 17] = [
15791579
("contains", 1),
15801580
("starts_with", 1),
15811581
("ends_with", 1),

clippy_lints/src/needless_continue.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,15 +252,15 @@ struct LintData<'a> {
252252
block_stmts: &'a [ast::Stmt],
253253
}
254254

255-
const MSG_REDUNDANT_ELSE_BLOCK: &'static str = "This else block is redundant.\n";
255+
const MSG_REDUNDANT_ELSE_BLOCK: &str = "This else block is redundant.\n";
256256

257-
const MSG_ELSE_BLOCK_NOT_NEEDED: &'static str = "There is no need for an explicit `else` block for this `if` \
257+
const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \
258258
expression\n";
259259

260-
const DROP_ELSE_BLOCK_AND_MERGE_MSG: &'static str = "Consider dropping the else clause and merging the code that \
260+
const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the else clause and merging the code that \
261261
follows (in the loop) with the if block, like so:\n";
262262

263-
const DROP_ELSE_BLOCK_MSG: &'static str = "Consider dropping the else clause, and moving out the code in the else \
263+
const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \
264264
block, like so:\n";
265265

266266

clippy_lints/src/non_expressive_names.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> {
6969
// this list contains lists of names that are allowed to be similar
7070
// the assumption is that no name is ever contained in multiple lists.
7171
#[cfg_attr(rustfmt, rustfmt_skip)]
72-
const WHITELIST: &'static [&'static [&'static str]] = &[
72+
const WHITELIST: &[&[&str]] = &[
7373
&["parsed", "parser"],
7474
&["lhs", "rhs"],
7575
&["tx", "rx"],

clippy_lints/src/utils/conf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ define_Conf! {
182182
/// Search for the configuration file.
183183
pub fn lookup_conf_file() -> io::Result<Option<path::PathBuf>> {
184184
/// Possible filename to search for.
185-
const CONFIG_FILE_NAMES: [&'static str; 2] = [".clippy.toml", "clippy.toml"];
185+
const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"];
186186

187187
let mut current = try!(env::current_dir());
188188

clippy_lints/src/utils/constants.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/// See also [the reference][reference-types] for a list of such types.
88
///
99
/// [reference-types]: https://doc.rust-lang.org/reference.html#types
10-
pub const BUILTIN_TYPES: &'static [&'static str] = &[
10+
pub const BUILTIN_TYPES: &[&str] = &[
1111
"i8",
1212
"u8",
1313
"i16",

clippy_lints/src/utils/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool {
169169

170170
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
171171
fn root_mode(&self) -> &ty::item_path::RootMode {
172-
const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
172+
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
173173
ABSOLUTE
174174
}
175175

0 commit comments

Comments
 (0)