@@ -137,6 +137,81 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
137
137
self . check_import_as_underscore ( item, * id) ;
138
138
}
139
139
}
140
+
141
+ fn report_unused_extern_crate_items (
142
+ & mut self ,
143
+ maybe_unused_extern_crates : FxHashMap < ast:: NodeId , Span > ,
144
+ ) {
145
+ let tcx = self . r . tcx ( ) ;
146
+ for extern_crate in & self . extern_crate_items {
147
+ let warn_if_unused = !extern_crate. ident . name . as_str ( ) . starts_with ( '_' ) ;
148
+
149
+ // If the crate is fully unused, we suggest removing it altogether.
150
+ // We do this in any edition.
151
+ if warn_if_unused {
152
+ if let Some ( & span) = maybe_unused_extern_crates. get ( & extern_crate. id ) {
153
+ self . r . lint_buffer . buffer_lint_with_diagnostic (
154
+ UNUSED_EXTERN_CRATES ,
155
+ extern_crate. id ,
156
+ span,
157
+ "unused extern crate" ,
158
+ BuiltinLintDiag :: UnusedExternCrate {
159
+ removal_span : extern_crate. span_with_attributes ,
160
+ } ,
161
+ ) ;
162
+ continue ;
163
+ }
164
+ }
165
+
166
+ // If we are not in Rust 2018 edition, then we don't make any further
167
+ // suggestions.
168
+ if !tcx. sess . at_least_rust_2018 ( ) {
169
+ continue ;
170
+ }
171
+
172
+ // If the extern crate has any attributes, they may have funky
173
+ // semantics we can't faithfully represent using `use` (most
174
+ // notably `#[macro_use]`). Ignore it.
175
+ if extern_crate. has_attrs {
176
+ continue ;
177
+ }
178
+
179
+ // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
180
+ // would not insert the new name into the prelude, where other imports in the crate may be
181
+ // expecting it.
182
+ if extern_crate. renames {
183
+ continue ;
184
+ }
185
+
186
+ // If the extern crate isn't in the extern prelude,
187
+ // there is no way it can be written as a `use`.
188
+ if !self
189
+ . r
190
+ . extern_prelude
191
+ . get ( & extern_crate. ident )
192
+ . is_some_and ( |entry| !entry. introduced_by_item )
193
+ {
194
+ continue ;
195
+ }
196
+
197
+ let vis_span = extern_crate
198
+ . vis_span
199
+ . find_ancestor_inside ( extern_crate. span )
200
+ . unwrap_or ( extern_crate. vis_span ) ;
201
+ let ident_span = extern_crate
202
+ . ident
203
+ . span
204
+ . find_ancestor_inside ( extern_crate. span )
205
+ . unwrap_or ( extern_crate. ident . span ) ;
206
+ self . r . lint_buffer . buffer_lint_with_diagnostic (
207
+ UNUSED_EXTERN_CRATES ,
208
+ extern_crate. id ,
209
+ extern_crate. span ,
210
+ "`extern crate` is not idiomatic in the new edition" ,
211
+ BuiltinLintDiag :: ExternCrateNotIdiomatic { vis_span, ident_span } ,
212
+ ) ;
213
+ }
214
+ }
140
215
}
141
216
142
217
impl < ' a , ' b , ' tcx > Visitor < ' a > for UnusedImportCheckVisitor < ' a , ' b , ' tcx > {
@@ -335,6 +410,8 @@ impl Resolver<'_, '_> {
335
410
} ;
336
411
visit:: walk_crate ( & mut visitor, krate) ;
337
412
413
+ visitor. report_unused_extern_crate_items ( maybe_unused_extern_crates) ;
414
+
338
415
for unused in visitor. unused_imports . values ( ) {
339
416
let mut fixes = Vec :: new ( ) ;
340
417
let spans = match calc_unused_spans ( unused, & unused. use_tree , unused. use_tree_id ) {
@@ -416,75 +493,6 @@ impl Resolver<'_, '_> {
416
493
) ;
417
494
}
418
495
419
- for extern_crate in visitor. extern_crate_items {
420
- let warn_if_unused = !extern_crate. ident . name . as_str ( ) . starts_with ( '_' ) ;
421
-
422
- // If the crate is fully unused, we suggest removing it altogether.
423
- // We do this in any edition.
424
- if warn_if_unused {
425
- if let Some ( & span) = maybe_unused_extern_crates. get ( & extern_crate. id ) {
426
- visitor. r . lint_buffer . buffer_lint_with_diagnostic (
427
- UNUSED_EXTERN_CRATES ,
428
- extern_crate. id ,
429
- span,
430
- "unused extern crate" ,
431
- BuiltinLintDiag :: UnusedExternCrate {
432
- removal_span : extern_crate. span_with_attributes ,
433
- } ,
434
- ) ;
435
- continue ;
436
- }
437
- }
438
-
439
- // If we are not in Rust 2018 edition, then we don't make any further
440
- // suggestions.
441
- if !tcx. sess . at_least_rust_2018 ( ) {
442
- continue ;
443
- }
444
-
445
- // If the extern crate has any attributes, they may have funky
446
- // semantics we can't faithfully represent using `use` (most
447
- // notably `#[macro_use]`). Ignore it.
448
- if extern_crate. has_attrs {
449
- continue ;
450
- }
451
-
452
- // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
453
- // would not insert the new name into the prelude, where other imports in the crate may be
454
- // expecting it.
455
- if extern_crate. renames {
456
- continue ;
457
- }
458
-
459
- // If the extern crate isn't in the extern prelude,
460
- // there is no way it can be written as a `use`.
461
- if !visitor
462
- . r
463
- . extern_prelude
464
- . get ( & extern_crate. ident )
465
- . is_some_and ( |entry| !entry. introduced_by_item )
466
- {
467
- continue ;
468
- }
469
-
470
- let vis_span = extern_crate
471
- . vis_span
472
- . find_ancestor_inside ( extern_crate. span )
473
- . unwrap_or ( extern_crate. vis_span ) ;
474
- let ident_span = extern_crate
475
- . ident
476
- . span
477
- . find_ancestor_inside ( extern_crate. span )
478
- . unwrap_or ( extern_crate. ident . span ) ;
479
- visitor. r . lint_buffer . buffer_lint_with_diagnostic (
480
- UNUSED_EXTERN_CRATES ,
481
- extern_crate. id ,
482
- extern_crate. span ,
483
- "`extern crate` is not idiomatic in the new edition" ,
484
- BuiltinLintDiag :: ExternCrateNotIdiomatic { vis_span, ident_span } ,
485
- ) ;
486
- }
487
-
488
496
let unused_imports = visitor. unused_imports ;
489
497
let mut check_redundant_imports = FxIndexSet :: default ( ) ;
490
498
for module in self . arenas . local_modules ( ) . iter ( ) {
0 commit comments