@@ -32,9 +32,10 @@ use rustc_ast::visit::{self, Visitor};
3232use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
3333use rustc_data_structures:: unord:: UnordSet ;
3434use rustc_errors:: { pluralize, MultiSpan } ;
35+ use rustc_hir:: def:: { DefKind , Res } ;
3536use rustc_session:: lint:: builtin:: { MACRO_USE_EXTERN_CRATE , UNUSED_EXTERN_CRATES , UNUSED_IMPORTS } ;
3637use rustc_session:: lint:: BuiltinLintDiagnostics ;
37- use rustc_span:: symbol:: Ident ;
38+ use rustc_span:: symbol:: { kw , Ident } ;
3839use rustc_span:: { Span , DUMMY_SP } ;
3940
4041struct UnusedImport < ' a > {
@@ -58,6 +59,7 @@ struct UnusedImportCheckVisitor<'a, 'b, 'tcx> {
5859 base_use_tree : Option < & ' a ast:: UseTree > ,
5960 base_id : ast:: NodeId ,
6061 item_span : Span ,
62+ base_use_is_pub : bool ,
6163}
6264
6365struct ExternCrateToLint {
@@ -110,6 +112,35 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
110112 unused : Default :: default ( ) ,
111113 } )
112114 }
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+ }
113144}
114145
115146impl < ' 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> {
119150 // whether they're used or not. Also ignore imports with a dummy span
120151 // because this means that they were generated in some fashion by the
121152 // 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 ( ) ,
123155 ast:: ItemKind :: ExternCrate ( orig_name) => {
124156 self . extern_crate_items . push ( ExternCrateToLint {
125157 id : item. id ,
@@ -146,6 +178,11 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
146178 self . base_use_tree = Some ( use_tree) ;
147179 }
148180
181+ if self . base_use_is_pub {
182+ self . check_import_as_underscore ( use_tree, id) ;
183+ return ;
184+ }
185+
149186 if let ast:: UseTreeKind :: Nested ( ref items) = use_tree. kind {
150187 if items. is_empty ( ) {
151188 self . unused_import ( self . base_id ) . add ( id) ;
@@ -300,6 +337,7 @@ impl Resolver<'_, '_> {
300337 base_use_tree : None ,
301338 base_id : ast:: DUMMY_NODE_ID ,
302339 item_span : DUMMY_SP ,
340+ base_use_is_pub : false ,
303341 } ;
304342 visit:: walk_crate ( & mut visitor, krate) ;
305343
0 commit comments