]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/const_static_lifetime.rs
Auto merge of #3705 - matthiaskrgr:rustup, r=phansch
[rust.git] / clippy_lints / src / const_static_lifetime.rs
1 use crate::utils::{in_macro, snippet, span_lint_and_then};
2 use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
3 use rustc::{declare_tool_lint, lint_array};
4 use rustc_errors::Applicability;
5 use syntax::ast::*;
6
7 /// **What it does:** Checks for constants with an explicit `'static` lifetime.
8 ///
9 /// **Why is this bad?** Adding `'static` to every reference can create very
10 /// complicated types.
11 ///
12 /// **Known problems:** None.
13 ///
14 /// **Example:**
15 /// ```rust
16 /// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
17 /// &[...]
18 /// ```
19 /// This code can be rewritten as
20 /// ```rust
21 ///  const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
22 /// ```
23 declare_clippy_lint! {
24     pub CONST_STATIC_LIFETIME,
25     style,
26     "Using explicit `'static` lifetime for constants when elision rules would allow omitting them."
27 }
28
29 pub struct StaticConst;
30
31 impl LintPass for StaticConst {
32     fn get_lints(&self) -> LintArray {
33         lint_array!(CONST_STATIC_LIFETIME)
34     }
35
36     fn name(&self) -> &'static str {
37         "StaticConst"
38     }
39 }
40
41 impl StaticConst {
42     // Recursively visit types
43     fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>) {
44         match ty.node {
45             // Be careful of nested structures (arrays and tuples)
46             TyKind::Array(ref ty, _) => {
47                 self.visit_type(&*ty, cx);
48             },
49             TyKind::Tup(ref tup) => {
50                 for tup_ty in tup {
51                     self.visit_type(&*tup_ty, cx);
52                 }
53             },
54             // This is what we are looking for !
55             TyKind::Rptr(ref optional_lifetime, ref borrow_type) => {
56                 // Match the 'static lifetime
57                 if let Some(lifetime) = *optional_lifetime {
58                     match borrow_type.ty.node {
59                         TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
60                             if lifetime.ident.name == "'static" {
61                                 let snip = snippet(cx, borrow_type.ty.span, "<type>");
62                                 let sugg = format!("&{}", snip);
63                                 span_lint_and_then(
64                                     cx,
65                                     CONST_STATIC_LIFETIME,
66                                     lifetime.ident.span,
67                                     "Constants have by default a `'static` lifetime",
68                                     |db| {
69                                         db.span_suggestion(
70                                             ty.span,
71                                             "consider removing `'static`",
72                                             sugg,
73                                             Applicability::MachineApplicable, //snippet
74                                         );
75                                     },
76                                 );
77                             }
78                         },
79                         _ => {},
80                     }
81                 }
82                 self.visit_type(&*borrow_type.ty, cx);
83             },
84             TyKind::Slice(ref ty) => {
85                 self.visit_type(ty, cx);
86             },
87             _ => {},
88         }
89     }
90 }
91
92 impl EarlyLintPass for StaticConst {
93     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
94         if !in_macro(item.span) {
95             // Match only constants...
96             if let ItemKind::Const(ref var_type, _) = item.node {
97                 self.visit_type(var_type, cx);
98             }
99         }
100     }
101
102     // Don't check associated consts because `'static` cannot be elided on those (issue #2438)
103 }