11use clippy_utils:: diagnostics:: span_lint;
22
33use rustc_data_structures:: fx:: FxHashSet ;
4- use rustc_hir:: { def:: Res , Item , ItemKind , PolyTraitRef , TraitBoundModifier , Ty , TyKind , UseKind } ;
4+ use rustc_hir:: {
5+ def:: Res , def_id:: DefId , Crate , Item , ItemKind , PolyTraitRef , TraitBoundModifier , Ty , TyKind , UseKind ,
6+ } ;
57use rustc_lint:: { LateContext , LateLintPass } ;
68use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
79use rustc_span:: { Span , Symbol } ;
@@ -11,14 +13,7 @@ declare_clippy_lint! {
1113 ///
1214 /// **Why is this bad?** Some types are undesirable in certain contexts.
1315 ///
14- /// **Known problems:** The fully qualified path must be used. This lint
15- /// doesn't support aliases or reexported names; be aware that many types
16- /// in `std` are actually reexports.
17- ///
18- /// For example, if you want to disallow `BTreeMap`, your clippy.toml
19- /// configuration would look like
20- /// `disallowed-methods = ["alloc::collections::btree::map::BTreeMap"]` and not
21- /// `disallowed-methods = ["std::collections::BTreeMap"]` as you might expect.
16+ /// **Known problems:** None.
2217 ///
2318 /// N.B. There is no way to ban primitive types.
2419 ///
@@ -27,7 +22,7 @@ declare_clippy_lint! {
2722 /// An example clippy.toml configuration:
2823 /// ```toml
2924 /// # clippy.toml
30- /// disallowed-methods = ["alloc ::collections::btree::map ::BTreeMap"]
25+ /// disallowed-methods = ["std ::collections::BTreeMap"]
3126 /// ```
3227 ///
3328 /// ```rust,ignore
@@ -47,6 +42,7 @@ declare_clippy_lint! {
4742#[ derive( Clone , Debug ) ]
4843pub struct DisallowedType {
4944 disallowed : FxHashSet < Vec < Symbol > > ,
45+ def_ids : FxHashSet < ( DefId , Vec < Symbol > ) > ,
5046}
5147
5248impl DisallowedType {
@@ -56,19 +52,29 @@ impl DisallowedType {
5652 . iter ( )
5753 . map ( |s| s. split ( "::" ) . map ( |seg| Symbol :: intern ( seg) ) . collect :: < Vec < _ > > ( ) )
5854 . collect ( ) ,
55+ def_ids : FxHashSet :: default ( ) ,
5956 }
6057 }
6158}
6259
6360impl_lint_pass ! ( DisallowedType => [ DISALLOWED_TYPE ] ) ;
6461
6562impl < ' tcx > LateLintPass < ' tcx > for DisallowedType {
63+ fn check_crate ( & mut self , cx : & LateContext < ' _ > , _: & Crate < ' _ > ) {
64+ for path in & self . disallowed {
65+ let segs = path. iter ( ) . map ( ToString :: to_string) . collect :: < Vec < _ > > ( ) ;
66+ if let Res :: Def ( _, id) = clippy_utils:: path_to_res ( cx, & segs. iter ( ) . map ( String :: as_str) . collect :: < Vec < _ > > ( ) )
67+ {
68+ self . def_ids . insert ( ( id, path. clone ( ) ) ) ;
69+ }
70+ }
71+ }
72+
6673 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) {
6774 if_chain ! {
6875 if let ItemKind :: Use ( path, UseKind :: Single ) = & item. kind;
69- if let Res :: Def ( _, id) = path. res;
70- let use_path = cx. get_def_path( id) ;
71- if let Some ( name) = self . disallowed. iter( ) . find( |path| * * path == use_path) ;
76+ if let Res :: Def ( _, did) = path. res;
77+ if let Some ( ( _, name) ) = self . def_ids. iter( ) . find( |( id, _) | * id == did) ;
7278 then {
7379 emit( cx, name, item. span, ) ;
7480 }
@@ -79,8 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedType {
7985 if_chain ! {
8086 if let TyKind :: Path ( path) = & ty. kind;
8187 if let Some ( did) = cx. qpath_res( path, ty. hir_id) . opt_def_id( ) ;
82- let use_path = cx. get_def_path( did) ;
83- if let Some ( name) = self . disallowed. iter( ) . find( |path| * * path == use_path) ;
88+ if let Some ( ( _, name) ) = self . def_ids. iter( ) . find( |( id, _) | * id == did) ;
8489 then {
8590 emit( cx, name, path. span( ) ) ;
8691 }
@@ -90,8 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedType {
9095 fn check_poly_trait_ref ( & mut self , cx : & LateContext < ' tcx > , poly : & ' tcx PolyTraitRef < ' tcx > , _: TraitBoundModifier ) {
9196 if_chain ! {
9297 if let Res :: Def ( _, did) = poly. trait_ref. path. res;
93- let use_path = cx. get_def_path( did) ;
94- if let Some ( name) = self . disallowed. iter( ) . find( |path| * * path == use_path) ;
98+ if let Some ( ( _, name) ) = self . def_ids. iter( ) . find( |( id, _) | * id == did) ;
9599 then {
96100 emit( cx, name, poly. trait_ref. path. span) ;
97101 }
0 commit comments