1- use std:: ops:: ControlFlow ;
2-
31use clippy_utils:: diagnostics:: span_lint_and_sugg;
42use clippy_utils:: source:: snippet_opt;
53use rustc_errors:: Applicability ;
64use rustc_hir:: def:: { DefKind , Res } ;
7- use rustc_hir:: def_id:: DefId ;
8- use rustc_hir:: definitions:: DefPathData ;
9- use rustc_hir:: intravisit:: { walk_item, walk_mod, walk_path, Visitor } ;
10- use rustc_hir:: { HirId , Item , ItemKind , Node , Path , UseKind } ;
5+ use rustc_hir:: { Item , ItemKind , UseKind } ;
116use rustc_lint:: { LateContext , LateLintPass } ;
12- use rustc_middle:: hir:: nested_filter;
137use rustc_middle:: ty:: Visibility ;
148use rustc_session:: declare_lint_pass;
159use rustc_span:: symbol:: kw;
@@ -51,17 +45,15 @@ declare_lint_pass!(AnonTraitImport => [ANON_TRAIT_IMPORT]);
5145
5246impl < ' tcx > LateLintPass < ' tcx > for AnonTraitImport {
5347 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) {
54- let module = cx. tcx . parent_module_from_def_id ( item. owner_id . def_id ) ;
55- if cx. tcx . visibility ( item. owner_id . def_id ) != Visibility :: Restricted ( module. to_def_id ( ) ) {
56- return ;
57- }
5848 if let ItemKind :: Use ( path, UseKind :: Single ) = item. kind
5949 // Ignore imports that already use Underscore
6050 && item. ident . name != kw:: Underscore
61- && let Some ( Res :: Def ( DefKind :: Trait , def_id) ) = path. res . first ( )
62- && let parent_id = cx. tcx . hir ( ) . get_parent_item ( item. hir_id ( ) )
63- && let Node :: Item ( parent_item) = cx. tcx . hir_node_by_def_id ( parent_id. def_id )
64- && !is_import_used_by_name_in_item ( cx, * def_id, parent_item)
51+ // Only check traits
52+ && let Some ( Res :: Def ( DefKind :: Trait , _) ) = path. res . first ( )
53+ && cx. tcx . maybe_unused_trait_imports ( ( ) ) . contains ( & item. owner_id . def_id )
54+ // Only check this use if it is only visible to its module (no pub, pub(crate), ...)
55+ && let module = cx. tcx . parent_module_from_def_id ( item. owner_id . def_id )
56+ && cx. tcx . visibility ( item. owner_id . def_id ) == Visibility :: Restricted ( module. to_def_id ( ) )
6557 && let Some ( last_segment) = path. segments . last ( )
6658 && let Some ( snip) = snippet_opt ( cx, last_segment. ident . span )
6759 {
@@ -78,140 +70,3 @@ impl<'tcx> LateLintPass<'tcx> for AnonTraitImport {
7870 }
7971 }
8072}
81-
82- fn is_import_used_by_name_in_item < ' tcx > ( cx : & LateContext < ' tcx > , def_id : DefId , parent_item : & ' tcx Item < ' _ > ) -> bool {
83- let module = find_module ( cx, parent_item) ;
84- let mut visitor = TraitUsedByNameVisitor {
85- cx,
86- id : def_id,
87- module,
88- module_depth : 0 ,
89- } ;
90- let result = if let ItemKind :: Mod ( parent_mod) = parent_item. kind {
91- visitor. visit_mod ( parent_mod, parent_item. span , parent_item. hir_id ( ) )
92- } else {
93- visitor. visit_item ( parent_item)
94- } ;
95- matches ! ( result, ControlFlow :: Break ( ( ) ) )
96- }
97-
98- fn find_module < ' tcx > ( cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > ) -> HirId {
99- if let ItemKind :: Mod ( _) = & item. kind {
100- return item. hir_id ( ) ;
101- }
102- let parent = cx. tcx . hir ( ) . get_parent_item ( item. hir_id ( ) ) ;
103- let mut node = cx. tcx . hir_node_by_def_id ( parent. def_id ) ;
104- loop {
105- match node {
106- Node :: Crate ( r#mod) => return r#mod. item_ids [ 0 ] . hir_id ( ) ,
107- Node :: Item ( item) => {
108- if let ItemKind :: Mod ( _) = & item. kind {
109- return item. hir_id ( ) ;
110- }
111- let hir_id = item. hir_id ( ) ;
112- let parent = cx. tcx . hir ( ) . get_parent_item ( hir_id) ;
113- node = cx. tcx . hir_node_by_def_id ( parent. def_id ) ;
114- } ,
115- _ => panic ! ( "not an item or crate: {node:?}" ) ,
116- } ;
117- }
118- }
119-
120- struct TraitUsedByNameVisitor < ' a , ' hir > {
121- cx : & ' a LateContext < ' hir > ,
122- id : DefId ,
123- module : HirId ,
124- module_depth : usize ,
125- }
126-
127- impl < ' a , ' hir > Visitor < ' hir > for TraitUsedByNameVisitor < ' a , ' hir > {
128- type NestedFilter = nested_filter:: All ;
129- type Result = ControlFlow < ( ) > ;
130-
131- fn nested_visit_map ( & mut self ) -> Self :: Map {
132- self . cx . tcx . hir ( )
133- }
134-
135- fn visit_item ( & mut self , item : & ' hir Item < ' _ > ) -> Self :: Result {
136- match item. kind {
137- ItemKind :: Mod ( m) => {
138- self . module_depth += 1 ;
139- let result = walk_mod ( self , m, item. hir_id ( ) ) ;
140- self . module_depth -= 1 ;
141- result
142- } ,
143- _ => walk_item ( self , item) ,
144- }
145- }
146-
147- fn visit_path ( & mut self , path : & Path < ' hir > , _: HirId ) -> Self :: Result {
148- if self . module_depth > 0 {
149- if let Some ( segment) = path. segments . first ( )
150- && segment. ident . name == kw:: Crate
151- {
152- if let Some ( mod_segment) = path. segments . get ( path. segments . len ( ) - 2 )
153- && Some ( self . module . owner . to_def_id ( ) ) == mod_segment. res . mod_def_id ( )
154- && path. res . opt_def_id ( ) == Some ( self . id )
155- {
156- return ControlFlow :: Break ( ( ) ) ;
157- }
158- } else {
159- let mut super_count = 0 ;
160- for segment in path. segments {
161- if segment. ident . name == kw:: Super {
162- super_count += 1 ;
163- if super_count > self . module_depth {
164- break ;
165- }
166- } else {
167- if super_count == self . module_depth
168- && ( path. res . opt_def_id ( ) == Some ( self . id ) || segment. res . opt_def_id ( ) == Some ( self . id ) )
169- {
170- return ControlFlow :: Break ( ( ) ) ;
171- }
172- break ;
173- }
174- }
175- }
176- }
177- if let Some ( def_id) = self . first_path_segment_def_id ( path)
178- && def_id == self . id
179- && self . module_depth == 0
180- {
181- return ControlFlow :: Break ( ( ) ) ;
182- }
183- walk_path ( self , path)
184- }
185- }
186-
187- impl < ' hir > TraitUsedByNameVisitor < ' _ , ' hir > {
188- fn skip_def_id ( & self , def_id : DefId ) -> DefId {
189- let def_key = self . cx . tcx . def_key ( def_id) ;
190- match def_key. disambiguated_data . data {
191- DefPathData :: Ctor => {
192- if let Some ( def_id) = self . cx . tcx . opt_parent ( def_id) {
193- self . skip_def_id ( def_id)
194- } else {
195- def_id
196- }
197- } ,
198- _ => def_id,
199- }
200- }
201-
202- fn first_path_segment_def_id ( & self , path : & Path < ' _ > ) -> Option < DefId > {
203- path. res . opt_def_id ( ) . and_then ( |mut def_id| {
204- def_id = self . skip_def_id ( def_id) ;
205- for _ in path. segments . iter ( ) . skip ( 1 ) {
206- def_id = self . skip_def_id ( def_id) ;
207- if let Some ( parent_def_id) = self . cx . tcx . opt_parent ( def_id) {
208- def_id = parent_def_id;
209- } else {
210- return None ;
211- }
212- }
213-
214- Some ( def_id)
215- } )
216- }
217- }
0 commit comments