]> git.lizzy.rs Git - rust.git/blob - src/librustc/lint/internal.rs
22386b1c7a588dca2d3b07fcbc478e77bc83c0de
[rust.git] / src / librustc / lint / internal.rs
1 //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
2 //! Clippy.
3
4 use crate::hir::{Expr, ExprKind, PatKind, Path, QPath, Ty, TyKind};
5 use crate::lint::{
6     EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
7 };
8 use errors::Applicability;
9 use rustc_data_structures::fx::FxHashMap;
10 use syntax::ast::Ident;
11
12 declare_lint! {
13     pub DEFAULT_HASH_TYPES,
14     Warn,
15     "forbid HashMap and HashSet and suggest the FxHash* variants"
16 }
17
18 pub struct DefaultHashTypes {
19     map: FxHashMap<String, String>,
20 }
21
22 impl DefaultHashTypes {
23     pub fn new() -> Self {
24         let mut map = FxHashMap::default();
25         map.insert("HashMap".to_string(), "FxHashMap".to_string());
26         map.insert("HashSet".to_string(), "FxHashSet".to_string());
27         Self { map }
28     }
29 }
30
31 impl LintPass for DefaultHashTypes {
32     fn get_lints(&self) -> LintArray {
33         lint_array!(DEFAULT_HASH_TYPES)
34     }
35
36     fn name(&self) -> &'static str {
37         "DefaultHashTypes"
38     }
39 }
40
41 impl EarlyLintPass for DefaultHashTypes {
42     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
43         let ident_string = ident.to_string();
44         if let Some(replace) = self.map.get(&ident_string) {
45             let msg = format!(
46                 "Prefer {} over {}, it has better performance",
47                 replace, ident_string
48             );
49             let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
50             db.span_suggestion(
51                 ident.span,
52                 "use",
53                 replace.to_string(),
54                 Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
55             );
56             db.note(&format!(
57                 "a `use rustc_data_structures::fx::{}` may be necessary",
58                 replace
59             ))
60             .emit();
61         }
62     }
63 }
64
65 declare_lint! {
66     pub USAGE_OF_TY_TYKIND,
67     Warn,
68     "Usage of `ty::TyKind` outside of the `ty::sty` module"
69 }
70
71 pub struct TyKindUsage;
72
73 impl LintPass for TyKindUsage {
74     fn get_lints(&self) -> LintArray {
75         lint_array!(USAGE_OF_TY_TYKIND)
76     }
77
78     fn name(&self) -> &'static str {
79         "TyKindUsage"
80     }
81 }
82
83 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
84     fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &'tcx Expr) {
85         let qpaths = match &expr.node {
86             ExprKind::Match(_, arms, _) => {
87                 let mut qpaths = vec![];
88                 for arm in arms {
89                     for pat in &arm.pats {
90                         match &pat.node {
91                             PatKind::Path(qpath) | PatKind::TupleStruct(qpath, ..) => {
92                                 qpaths.push(qpath)
93                             }
94                             _ => (),
95                         }
96                     }
97                 }
98                 qpaths
99             }
100             ExprKind::Path(qpath) => vec![qpath],
101             _ => vec![],
102         };
103         for qpath in qpaths {
104             if let QPath::Resolved(_, path) = qpath {
105                 let segments_iter = path.segments.iter().rev().skip(1).rev();
106
107                 if let Some(last) = segments_iter.clone().last() {
108                     if last.ident.as_str() == "TyKind" {
109                         let path = Path {
110                             span: path.span.with_hi(last.ident.span.hi()),
111                             def: path.def,
112                             segments: segments_iter.cloned().collect(),
113                         };
114
115                         if let Some(def) = last.def {
116                             if def
117                                 .def_id()
118                                 .match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
119                             {
120                                 cx.struct_span_lint(
121                                     USAGE_OF_TY_TYKIND,
122                                     path.span,
123                                     "usage of `ty::TyKind::<kind>`",
124                                 )
125                                 .span_suggestion(
126                                     path.span,
127                                     "try using ty::<kind> directly",
128                                     "ty".to_string(),
129                                     Applicability::MaybeIncorrect, // ty maybe needs an import
130                                 )
131                                 .emit();
132                             }
133                         }
134                     }
135                 }
136             }
137         }
138     }
139
140     fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
141         if let TyKind::Path(qpath) = &ty.node {
142             if let QPath::Resolved(_, path) = qpath {
143                 if let Some(last) = path.segments.iter().last() {
144                     if last.ident.as_str() == "TyKind" {
145                         if let Some(def) = last.def {
146                             if def
147                                 .def_id()
148                                 .match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
149                             {
150                                 cx.struct_span_lint(
151                                     USAGE_OF_TY_TYKIND,
152                                     path.span,
153                                     "usage of `ty::TyKind`",
154                                 )
155                                 .help("try using `ty::Ty` instead")
156                                 .emit();
157                             }
158                         }
159                     }
160                 }
161             }
162         }
163     }
164 }