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;
7 /// **What it does:** Checks for constants with an explicit `'static` lifetime.
9 /// **Why is this bad?** Adding `'static` to every reference can create very
10 /// complicated types.
12 /// **Known problems:** None.
16 /// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
19 /// This code can be rewritten as
21 /// const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
23 declare_clippy_lint! {
24 pub CONST_STATIC_LIFETIME,
26 "Using explicit `'static` lifetime for constants when elision rules would allow omitting them."
29 pub struct StaticConst;
31 impl LintPass for StaticConst {
32 fn get_lints(&self) -> LintArray {
33 lint_array!(CONST_STATIC_LIFETIME)
38 // Recursively visit types
39 fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>) {
41 // Be careful of nested structures (arrays and tuples)
42 TyKind::Array(ref ty, _) => {
43 self.visit_type(&*ty, cx);
45 TyKind::Tup(ref tup) => {
47 self.visit_type(&*tup_ty, cx);
50 // This is what we are looking for !
51 TyKind::Rptr(ref optional_lifetime, ref borrow_type) => {
52 // Match the 'static lifetime
53 if let Some(lifetime) = *optional_lifetime {
54 match borrow_type.ty.node {
55 TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
56 if lifetime.ident.name == "'static" {
57 let snip = snippet(cx, borrow_type.ty.span, "<type>");
58 let sugg = format!("&{}", snip);
61 CONST_STATIC_LIFETIME,
63 "Constants have by default a `'static` lifetime",
65 db.span_suggestion_with_applicability(
67 "consider removing `'static`",
69 Applicability::MachineApplicable, //snippet
78 self.visit_type(&*borrow_type.ty, cx);
80 TyKind::Slice(ref ty) => {
81 self.visit_type(ty, cx);
88 impl EarlyLintPass for StaticConst {
89 fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
90 if !in_macro(item.span) {
91 // Match only constants...
92 if let ItemKind::Const(ref var_type, _) = item.node {
93 self.visit_type(var_type, cx);
98 // Don't check associated consts because `'static` cannot be elided on those (issue #2438)