@@ -32,9 +32,10 @@ use rustc_ast::visit::{self, Visitor};
32
32
use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
33
33
use rustc_data_structures:: unord:: UnordSet ;
34
34
use rustc_errors:: { pluralize, MultiSpan } ;
35
+ use rustc_hir:: def:: { DefKind , Res } ;
35
36
use rustc_session:: lint:: builtin:: { MACRO_USE_EXTERN_CRATE , UNUSED_EXTERN_CRATES , UNUSED_IMPORTS } ;
36
37
use rustc_session:: lint:: BuiltinLintDiagnostics ;
37
- use rustc_span:: symbol:: Ident ;
38
+ use rustc_span:: symbol:: { kw , Ident } ;
38
39
use rustc_span:: { Span , DUMMY_SP } ;
39
40
40
41
struct UnusedImport < ' a > {
@@ -58,6 +59,7 @@ struct UnusedImportCheckVisitor<'a, 'b, 'tcx> {
58
59
base_use_tree : Option < & ' a ast:: UseTree > ,
59
60
base_id : ast:: NodeId ,
60
61
item_span : Span ,
62
+ base_use_is_pub : bool ,
61
63
}
62
64
63
65
struct ExternCrateToLint {
@@ -110,6 +112,35 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
110
112
unused : Default :: default ( ) ,
111
113
} )
112
114
}
115
+
116
+ fn check_import_as_underscore ( & mut self , item : & ast:: UseTree , id : ast:: NodeId ) {
117
+ match item. kind {
118
+ ast:: UseTreeKind :: Simple ( Some ( ident) ) => {
119
+ if ident. name == kw:: Underscore
120
+ && !self
121
+ . r
122
+ . import_res_map
123
+ . get ( & id)
124
+ . map ( |per_ns| {
125
+ per_ns. iter ( ) . filter_map ( |res| res. as_ref ( ) ) . any ( |res| {
126
+ matches ! ( res, Res :: Def ( DefKind :: Trait | DefKind :: TraitAlias , _) )
127
+ } )
128
+ } )
129
+ . unwrap_or ( false )
130
+ {
131
+ self . unused_import ( self . base_id ) . add ( id) ;
132
+ }
133
+ }
134
+ ast:: UseTreeKind :: Nested ( ref items) => self . check_imports_as_underscore ( items) ,
135
+ _ => { }
136
+ }
137
+ }
138
+
139
+ fn check_imports_as_underscore ( & mut self , items : & [ ( ast:: UseTree , ast:: NodeId ) ] ) {
140
+ for ( item, id) in items {
141
+ self . check_import_as_underscore ( item, * id) ;
142
+ }
143
+ }
113
144
}
114
145
115
146
impl < ' a , ' b , ' tcx > Visitor < ' a > for UnusedImportCheckVisitor < ' a , ' b , ' tcx > {
@@ -119,7 +150,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
119
150
// whether they're used or not. Also ignore imports with a dummy span
120
151
// because this means that they were generated in some fashion by the
121
152
// compiler and we don't need to consider them.
122
- ast:: ItemKind :: Use ( ..) if item. vis . kind . is_pub ( ) || item. span . is_dummy ( ) => return ,
153
+ ast:: ItemKind :: Use ( ..) if item. span . is_dummy ( ) => return ,
154
+ ast:: ItemKind :: Use ( ..) => self . base_use_is_pub = item. vis . kind . is_pub ( ) ,
123
155
ast:: ItemKind :: ExternCrate ( orig_name) => {
124
156
self . extern_crate_items . push ( ExternCrateToLint {
125
157
id : item. id ,
@@ -146,6 +178,11 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
146
178
self . base_use_tree = Some ( use_tree) ;
147
179
}
148
180
181
+ if self . base_use_is_pub {
182
+ self . check_import_as_underscore ( use_tree, id) ;
183
+ return ;
184
+ }
185
+
149
186
if let ast:: UseTreeKind :: Nested ( ref items) = use_tree. kind {
150
187
if items. is_empty ( ) {
151
188
self . unused_import ( self . base_id ) . add ( id) ;
@@ -300,6 +337,7 @@ impl Resolver<'_, '_> {
300
337
base_use_tree : None ,
301
338
base_id : ast:: DUMMY_NODE_ID ,
302
339
item_span : DUMMY_SP ,
340
+ base_use_is_pub : false ,
303
341
} ;
304
342
visit:: walk_crate ( & mut visitor, krate) ;
305
343
0 commit comments