22//! Clippy.
33
44use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
5- use rustc_ast:: { ImplKind , Item , ItemKind } ;
6- use rustc_data_structures:: fx:: FxHashMap ;
5+ use rustc_ast as ast;
76use rustc_errors:: Applicability ;
87use rustc_hir:: def:: Res ;
9- use rustc_hir:: { GenericArg , HirId , MutTy , Mutability , Path , PathSegment , QPath , Ty , TyKind } ;
8+ use rustc_hir:: {
9+ GenericArg , HirId , Item , ItemKind , MutTy , Mutability , Node , Path , PathSegment , QPath , Ty ,
10+ TyKind ,
11+ } ;
1012use rustc_middle:: ty;
11- use rustc_session:: { declare_lint_pass, declare_tool_lint, impl_lint_pass } ;
13+ use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1214use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
13- use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
15+ use rustc_span:: symbol:: { kw, sym, Symbol } ;
1416
1517declare_tool_lint ! {
1618 pub rustc:: DEFAULT_HASH_TYPES ,
@@ -19,43 +21,35 @@ declare_tool_lint! {
1921 report_in_external_macro: true
2022}
2123
22- pub struct DefaultHashTypes {
23- map : FxHashMap < Symbol , Symbol > ,
24- }
25-
26- impl DefaultHashTypes {
27- // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself
28- #[ allow( rustc:: default_hash_types) ]
29- pub fn new ( ) -> Self {
30- let mut map = FxHashMap :: default ( ) ;
31- map. insert ( sym:: HashMap , sym:: FxHashMap ) ;
32- map. insert ( sym:: HashSet , sym:: FxHashSet ) ;
33- Self { map }
34- }
35- }
36-
37- impl_lint_pass ! ( DefaultHashTypes => [ DEFAULT_HASH_TYPES ] ) ;
24+ declare_lint_pass ! ( DefaultHashTypes => [ DEFAULT_HASH_TYPES ] ) ;
3825
39- impl EarlyLintPass for DefaultHashTypes {
40- fn check_ident ( & mut self , cx : & EarlyContext < ' _ > , ident : Ident ) {
41- if let Some ( replace) = self . map . get ( & ident. name ) {
42- cx. struct_span_lint ( DEFAULT_HASH_TYPES , ident. span , |lint| {
43- // FIXME: We can avoid a copy here. Would require us to take String instead of &str.
44- let msg = format ! ( "Prefer {} over {}, it has better performance" , replace, ident) ;
45- lint. build ( & msg)
46- . span_suggestion (
47- ident. span ,
48- "use" ,
49- replace. to_string ( ) ,
50- Applicability :: MaybeIncorrect , // FxHashMap, ... needs another import
51- )
52- . note ( & format ! (
53- "a `use rustc_data_structures::fx::{}` may be necessary" ,
54- replace
55- ) )
56- . emit ( ) ;
57- } ) ;
26+ impl LateLintPass < ' _ > for DefaultHashTypes {
27+ fn check_path ( & mut self , cx : & LateContext < ' _ > , path : & Path < ' _ > , hir_id : HirId ) {
28+ let def_id = match path. res {
29+ Res :: Def ( rustc_hir:: def:: DefKind :: Struct , id) => id,
30+ _ => return ,
31+ } ;
32+ if matches ! ( cx. tcx. hir( ) . get( hir_id) , Node :: Item ( Item { kind: ItemKind :: Use ( ..) , .. } ) ) {
33+ // don't lint imports, only actual usages
34+ return ;
5835 }
36+ let replace = if cx. tcx . is_diagnostic_item ( sym:: hashmap_type, def_id) {
37+ "FxHashMap"
38+ } else if cx. tcx . is_diagnostic_item ( sym:: hashset_type, def_id) {
39+ "FxHashSet"
40+ } else {
41+ return ;
42+ } ;
43+ cx. struct_span_lint ( DEFAULT_HASH_TYPES , path. span , |lint| {
44+ let msg = format ! (
45+ "prefer `{}` over `{}`, it has better performance" ,
46+ replace,
47+ cx. tcx. item_name( def_id)
48+ ) ;
49+ lint. build ( & msg)
50+ . note ( & format ! ( "a `use rustc_data_structures::fx::{}` may be necessary" , replace) )
51+ . emit ( ) ;
52+ } ) ;
5953 }
6054}
6155
@@ -242,8 +236,9 @@ declare_tool_lint! {
242236declare_lint_pass ! ( LintPassImpl => [ LINT_PASS_IMPL_WITHOUT_MACRO ] ) ;
243237
244238impl EarlyLintPass for LintPassImpl {
245- fn check_item ( & mut self , cx : & EarlyContext < ' _ > , item : & Item ) {
246- if let ItemKind :: Impl ( box ImplKind { of_trait : Some ( lint_pass) , .. } ) = & item. kind {
239+ fn check_item ( & mut self , cx : & EarlyContext < ' _ > , item : & ast:: Item ) {
240+ if let ast:: ItemKind :: Impl ( box ast:: ImplKind { of_trait : Some ( lint_pass) , .. } ) = & item. kind
241+ {
247242 if let Some ( last) = lint_pass. path . segments . last ( ) {
248243 if last. ident . name == sym:: LintPass {
249244 let expn_data = lint_pass. path . span . ctxt ( ) . outer_expn_data ( ) ;
0 commit comments