2 use rustc
::lint
::{EarlyContext, EarlyLintPass, LintArray, LintPass}
;
3 use utils
::{in_macro, snippet, span_lint_and_then}
;
5 /// **What it does:** Checks for constants with an explicit `'static` lifetime.
7 /// **Why is this bad?** Adding `'static` to every reference can create very
10 /// **Known problems:** None.
14 /// const FOO: &'static [(&'static str, &'static str, fn(&Bar) -> bool)] =
17 /// This code can be rewritten as
19 /// const FOO: &[(&str, &str, fn(&Bar) -> bool)] = &[...]
22 pub CONST_STATIC_LIFETIME
,
24 "Using explicit `'static` lifetime for constants when elision rules would allow omitting them."
27 pub struct StaticConst
;
29 impl LintPass
for StaticConst
{
30 fn get_lints(&self) -> LintArray
{
31 lint_array
!(CONST_STATIC_LIFETIME
)
36 // Recursively visit types
37 fn visit_type(&mut self, ty
: &Ty
, cx
: &EarlyContext
) {
39 // Be careful of nested structures (arrays and tuples)
40 TyKind
::Array(ref ty
, _
) => {
41 self.visit_type(&*ty
, cx
);
43 TyKind
::Tup(ref tup
) => for tup_ty
in tup
{
44 self.visit_type(&*tup_ty
, cx
);
46 // This is what we are looking for !
47 TyKind
::Rptr(ref optional_lifetime
, ref borrow_type
) => {
48 // Match the 'static lifetime
49 if let Some(lifetime
) = *optional_lifetime
{
50 match borrow_type
.ty
.node
{
51 TyKind
::Path(..) | TyKind
::Slice(..) | TyKind
::Array(..) |
53 if lifetime
.ident
.name
== "'static" {
54 let snip
= snippet(cx
, borrow_type
.ty
.span
, "<type>");
55 let sugg
= format
!("&{}", snip
);
58 CONST_STATIC_LIFETIME
,
60 "Constants have by default a `'static` lifetime",
62 db
.span_suggestion(ty
.span
, "consider removing `'static`", sugg
);
70 self.visit_type(&*borrow_type
.ty
, cx
);
72 TyKind
::Slice(ref ty
) => {
73 self.visit_type(ty
, cx
);
80 impl EarlyLintPass
for StaticConst
{
81 fn check_item(&mut self, cx
: &EarlyContext
, item
: &Item
) {
82 if !in_macro(item
.span
) {
83 // Match only constants...
84 if let ItemKind
::Const(ref var_type
, _
) = item
.node
{
85 self.visit_type(var_type
, cx
);
90 fn check_trait_item(&mut self, cx
: &EarlyContext
, item
: &TraitItem
) {
91 if !in_macro(item
.span
) {
92 // Match only constants...
93 if let TraitItemKind
::Const(ref var_type
, _
) = item
.node
{
94 self.visit_type(var_type
, cx
);
99 fn check_impl_item(&mut self, cx
: &EarlyContext
, item
: &ImplItem
) {
100 if !in_macro(item
.span
) {
101 // Match only constants...
102 if let ImplItemKind
::Const(ref var_type
, _
) = item
.node
{
103 self.visit_type(var_type
, cx
);