@@ -3,9 +3,10 @@ use rustc::{declare_lint, lint_array};
3
3
use rustc:: hir:: * ;
4
4
use rustc:: hir;
5
5
use rustc:: hir:: intravisit:: { walk_expr, NestedVisitorMap , Visitor } ;
6
- use crate :: utils:: { match_qpath, paths, span_lint} ;
6
+ use rustc_data_structures:: fx:: FxHashMap ;
7
+ use crate :: utils:: { match_qpath, paths, span_lint, span_lint_and_sugg} ;
7
8
use syntax:: symbol:: LocalInternedString ;
8
- use syntax:: ast:: { Crate as AstCrate , ItemKind , Name } ;
9
+ use syntax:: ast:: { Crate as AstCrate , Ident , ItemKind , Name } ;
9
10
use syntax:: codemap:: Span ;
10
11
use std:: collections:: { HashMap , HashSet } ;
11
12
@@ -54,6 +55,18 @@ declare_clippy_lint! {
54
55
}
55
56
56
57
58
+ /// **What it does:** Checks for the presence of the default hash types "HashMap" or "HashSet"
59
+ /// and recommends the FxHash* variants.
60
+ ///
61
+ /// **Why is this bad?** The FxHash variants have better performance
62
+ /// and we don't need any collision prevention in clippy.
63
+ declare_clippy_lint ! {
64
+ pub DEFAULT_HASH_TYPES ,
65
+ internal,
66
+ "forbid HashMap and HashSet and suggest the FxHash* variants"
67
+ }
68
+
69
+
57
70
#[ derive( Copy , Clone ) ]
58
71
pub struct Clippy ;
59
72
@@ -207,3 +220,34 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> {
207
220
NestedVisitorMap :: All ( & self . cx . tcx . hir )
208
221
}
209
222
}
223
+
224
+
225
+
226
+ pub struct DefaultHashTypes {
227
+ map : FxHashMap < String , String > ,
228
+ }
229
+
230
+ impl DefaultHashTypes {
231
+ pub fn default ( ) -> Self {
232
+ let mut map = FxHashMap :: default ( ) ;
233
+ map. insert ( "HashMap" . to_owned ( ) , "FxHashMap" . to_owned ( ) ) ;
234
+ map. insert ( "HashSet" . to_owned ( ) , "FxHashSet" . to_owned ( ) ) ;
235
+ Self { map }
236
+ }
237
+ }
238
+
239
+ impl LintPass for DefaultHashTypes {
240
+ fn get_lints ( & self ) -> LintArray {
241
+ lint_array ! ( DEFAULT_HASH_TYPES )
242
+ }
243
+ }
244
+
245
+ impl EarlyLintPass for DefaultHashTypes {
246
+ fn check_ident ( & mut self , cx : & EarlyContext < ' _ > , ident : Ident ) {
247
+ let ident_string = ident. to_string ( ) ;
248
+ if let Some ( replace) = self . map . get ( & ident_string) {
249
+ let msg = format ! ( "Prefer {} over {}, it has better performance and we don't need any collision prevention in clippy" , replace, ident_string) ;
250
+ span_lint_and_sugg ( cx, DEFAULT_HASH_TYPES , ident. span , & msg, "use" , replace. to_owned ( ) ) ;
251
+ }
252
+ }
253
+ }
0 commit comments