1
- use std:: ops:: ControlFlow ;
2
-
3
1
use clippy_utils:: diagnostics:: span_lint_and_sugg;
4
2
use clippy_utils:: source:: snippet_opt;
5
3
use rustc_errors:: Applicability ;
6
4
use 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 } ;
11
6
use rustc_lint:: { LateContext , LateLintPass } ;
12
- use rustc_middle:: hir:: nested_filter;
13
7
use rustc_middle:: ty:: Visibility ;
14
8
use rustc_session:: declare_lint_pass;
15
9
use rustc_span:: symbol:: kw;
@@ -51,17 +45,15 @@ declare_lint_pass!(AnonTraitImport => [ANON_TRAIT_IMPORT]);
51
45
52
46
impl < ' tcx > LateLintPass < ' tcx > for AnonTraitImport {
53
47
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
- }
58
48
if let ItemKind :: Use ( path, UseKind :: Single ) = item. kind
59
49
// Ignore imports that already use Underscore
60
50
&& 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 ( ) )
65
57
&& let Some ( last_segment) = path. segments . last ( )
66
58
&& let Some ( snip) = snippet_opt ( cx, last_segment. ident . span )
67
59
{
@@ -78,140 +70,3 @@ impl<'tcx> LateLintPass<'tcx> for AnonTraitImport {
78
70
}
79
71
}
80
72
}
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