@@ -39,6 +39,7 @@ use rustc_session::lint::BuiltinLintDiag;
3939use rustc_span:: symbol:: { kw, Ident } ;
4040use rustc_span:: { Span , DUMMY_SP } ;
4141
42+ #[ derive( Debug ) ]
4243struct UnusedImport {
4344 use_tree : ast:: UseTree ,
4445 use_tree_id : ast:: NodeId ,
@@ -190,6 +191,40 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
190191 }
191192}
192193
194+ struct ImportFinderVisitor {
195+ unused_import : Option < UnusedImport > ,
196+ root_node_id : ast:: NodeId ,
197+ node_id : ast:: NodeId ,
198+ item_span : Span ,
199+ }
200+
201+ impl Visitor < ' _ > for ImportFinderVisitor {
202+ fn visit_item ( & mut self , item : & ast:: Item ) {
203+ match item. kind {
204+ ast:: ItemKind :: Use ( ..) if item. span . is_dummy ( ) => return ,
205+ _ => { }
206+ }
207+
208+ self . item_span = item. span_with_attributes ( ) ;
209+ visit:: walk_item ( self , item) ;
210+ }
211+
212+ fn visit_use_tree ( & mut self , use_tree : & ast:: UseTree , id : ast:: NodeId , _nested : bool ) {
213+ if id == self . root_node_id {
214+ let mut unused_import = UnusedImport {
215+ use_tree : use_tree. clone ( ) ,
216+ use_tree_id : id,
217+ item_span : self . item_span ,
218+ unused : Default :: default ( ) ,
219+ } ;
220+ unused_import. unused . insert ( self . node_id ) ;
221+ self . unused_import = Some ( unused_import) ;
222+ }
223+ visit:: walk_use_tree ( self , use_tree, id) ;
224+ }
225+ }
226+
227+ #[ derive( Debug ) ]
193228enum UnusedSpanResult {
194229 Used ,
195230 FlatUnused ( Span , Span ) ,
@@ -507,7 +542,36 @@ impl Resolver<'_, '_> {
507542 }
508543
509544 for import in check_redundant_imports {
510- self . check_for_redundant_imports ( import) ;
545+ if let Some ( redundant_spans) = self . check_for_redundant_imports ( import)
546+ && let ImportKind :: Single { source, id, .. } = import. kind
547+ {
548+ let mut visitor = ImportFinderVisitor {
549+ node_id : id,
550+ root_node_id : import. root_id ,
551+ unused_import : None ,
552+ item_span : Span :: default ( ) ,
553+ } ;
554+ visit:: walk_crate ( & mut visitor, krate) ;
555+ if let Some ( unused) = visitor. unused_import {
556+ let remove_span =
557+ match calc_unused_spans ( & unused, & unused. use_tree , unused. use_tree_id ) {
558+ UnusedSpanResult :: FlatUnused ( _, remove) => remove,
559+ UnusedSpanResult :: NestedFullUnused ( _, remove) => remove,
560+ UnusedSpanResult :: NestedPartialUnused ( _, removes) => {
561+ assert_eq ! ( removes. len( ) , 1 ) ;
562+ removes[ 0 ]
563+ }
564+ _ => import. use_span ,
565+ } ;
566+ self . lint_buffer . buffer_lint_with_diagnostic (
567+ UNUSED_IMPORTS ,
568+ id,
569+ import. span ,
570+ format ! ( "the item `{source}` is imported redundantly" ) ,
571+ BuiltinLintDiag :: RedundantImport ( redundant_spans, source, remove_span) ,
572+ ) ;
573+ }
574+ }
511575 }
512576 }
513577}
0 commit comments