@@ -128,7 +128,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
128
128
self . unused_import ( self . base_id ) . add ( id) ;
129
129
}
130
130
}
131
- ast:: UseTreeKind :: Nested ( ref items) => self . check_imports_as_underscore ( items) ,
131
+ ast:: UseTreeKind :: Nested { ref items, .. } => self . check_imports_as_underscore ( items) ,
132
132
_ => { }
133
133
}
134
134
}
@@ -254,7 +254,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
254
254
return ;
255
255
}
256
256
257
- if let ast:: UseTreeKind :: Nested ( ref items) = use_tree. kind {
257
+ if let ast:: UseTreeKind :: Nested { ref items, .. } = use_tree. kind {
258
258
if items. is_empty ( ) {
259
259
self . unused_import ( self . base_id ) . add ( id) ;
260
260
}
@@ -268,9 +268,8 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
268
268
269
269
enum UnusedSpanResult {
270
270
Used ,
271
- FlatUnused ( Span , Span ) ,
272
- NestedFullUnused ( Vec < Span > , Span ) ,
273
- NestedPartialUnused ( Vec < Span > , Vec < Span > ) ,
271
+ Unused { spans : Vec < Span > , remove : Span } ,
272
+ PartialUnused { spans : Vec < Span > , remove : Vec < Span > } ,
274
273
}
275
274
276
275
fn calc_unused_spans (
@@ -288,36 +287,33 @@ fn calc_unused_spans(
288
287
match use_tree. kind {
289
288
ast:: UseTreeKind :: Simple ( ..) | ast:: UseTreeKind :: Glob => {
290
289
if unused_import. unused . contains ( & use_tree_id) {
291
- UnusedSpanResult :: FlatUnused ( use_tree. span , full_span)
290
+ UnusedSpanResult :: Unused { spans : vec ! [ use_tree. span] , remove : full_span }
292
291
} else {
293
292
UnusedSpanResult :: Used
294
293
}
295
294
}
296
- ast:: UseTreeKind :: Nested ( ref nested) => {
295
+ ast:: UseTreeKind :: Nested { items : ref nested, span : tree_span } => {
297
296
if nested. is_empty ( ) {
298
- return UnusedSpanResult :: FlatUnused ( use_tree. span , full_span) ;
297
+ return UnusedSpanResult :: Unused { spans : vec ! [ use_tree. span] , remove : full_span } ;
299
298
}
300
299
301
300
let mut unused_spans = Vec :: new ( ) ;
302
301
let mut to_remove = Vec :: new ( ) ;
303
- let mut all_nested_unused = true ;
302
+ let mut used_childs = 0 ;
303
+ let mut contains_self = false ;
304
304
let mut previous_unused = false ;
305
305
for ( pos, ( use_tree, use_tree_id) ) in nested. iter ( ) . enumerate ( ) {
306
306
let remove = match calc_unused_spans ( unused_import, use_tree, * use_tree_id) {
307
307
UnusedSpanResult :: Used => {
308
- all_nested_unused = false ;
308
+ used_childs += 1 ;
309
309
None
310
310
}
311
- UnusedSpanResult :: FlatUnused ( span, remove) => {
312
- unused_spans. push ( span) ;
313
- Some ( remove)
314
- }
315
- UnusedSpanResult :: NestedFullUnused ( mut spans, remove) => {
311
+ UnusedSpanResult :: Unused { mut spans, remove } => {
316
312
unused_spans. append ( & mut spans) ;
317
313
Some ( remove)
318
314
}
319
- UnusedSpanResult :: NestedPartialUnused ( mut spans, mut to_remove_extra) => {
320
- all_nested_unused = false ;
315
+ UnusedSpanResult :: PartialUnused { mut spans, remove : mut to_remove_extra } => {
316
+ used_childs += 1 ;
321
317
unused_spans. append ( & mut spans) ;
322
318
to_remove. append ( & mut to_remove_extra) ;
323
319
None
@@ -326,7 +322,7 @@ fn calc_unused_spans(
326
322
if let Some ( remove) = remove {
327
323
let remove_span = if nested. len ( ) == 1 {
328
324
remove
329
- } else if pos == nested. len ( ) - 1 || !all_nested_unused {
325
+ } else if pos == nested. len ( ) - 1 || used_childs > 0 {
330
326
// Delete everything from the end of the last import, to delete the
331
327
// previous comma
332
328
nested[ pos - 1 ] . 0 . span . shrink_to_hi ( ) . to ( use_tree. span )
@@ -344,14 +340,38 @@ fn calc_unused_spans(
344
340
to_remove. push ( remove_span) ;
345
341
}
346
342
}
343
+ contains_self |= use_tree. prefix == kw:: SelfLower
344
+ && matches ! ( use_tree. kind, ast:: UseTreeKind :: Simple ( None ) ) ;
347
345
previous_unused = remove. is_some ( ) ;
348
346
}
349
347
if unused_spans. is_empty ( ) {
350
348
UnusedSpanResult :: Used
351
- } else if all_nested_unused {
352
- UnusedSpanResult :: NestedFullUnused ( unused_spans, full_span)
349
+ } else if used_childs == 0 {
350
+ UnusedSpanResult :: Unused { spans : unused_spans, remove : full_span }
353
351
} else {
354
- UnusedSpanResult :: NestedPartialUnused ( unused_spans, to_remove)
352
+ // If there is only one remaining child that is used, the braces around the use
353
+ // tree are not needed anymore. In that case, we determine the span of the left
354
+ // brace and the right brace, and tell rustfix to remove them as well.
355
+ //
356
+ // This means that `use a::{B, C};` will be turned into `use a::B;` rather than
357
+ // `use a::{B};`, removing a rustfmt roundtrip.
358
+ //
359
+ // Note that we cannot remove the braces if the only item inside the use tree is
360
+ // `self`: `use foo::{self};` is valid Rust syntax, while `use foo::self;` errors
361
+ // out. We also cannot turn `use foo::{self}` into `use foo`, as the former doesn't
362
+ // import types with the same name as the module.
363
+ if used_childs == 1 && !contains_self {
364
+ // Left brace, from the start of the nested group to the first item.
365
+ to_remove. push (
366
+ tree_span. shrink_to_lo ( ) . to ( nested. first ( ) . unwrap ( ) . 0 . span . shrink_to_lo ( ) ) ,
367
+ ) ;
368
+ // Right brace, from the end of the last item to the end of the nested group.
369
+ to_remove. push (
370
+ nested. last ( ) . unwrap ( ) . 0 . span . shrink_to_hi ( ) . to ( tree_span. shrink_to_hi ( ) ) ,
371
+ ) ;
372
+ }
373
+
374
+ UnusedSpanResult :: PartialUnused { spans : unused_spans, remove : to_remove }
355
375
}
356
376
}
357
377
}
@@ -417,15 +437,11 @@ impl Resolver<'_, '_> {
417
437
let mut fixes = Vec :: new ( ) ;
418
438
let spans = match calc_unused_spans ( unused, & unused. use_tree , unused. use_tree_id ) {
419
439
UnusedSpanResult :: Used => continue ,
420
- UnusedSpanResult :: FlatUnused ( span, remove) => {
421
- fixes. push ( ( remove, String :: new ( ) ) ) ;
422
- vec ! [ span]
423
- }
424
- UnusedSpanResult :: NestedFullUnused ( spans, remove) => {
440
+ UnusedSpanResult :: Unused { spans, remove } => {
425
441
fixes. push ( ( remove, String :: new ( ) ) ) ;
426
442
spans
427
443
}
428
- UnusedSpanResult :: NestedPartialUnused ( spans, remove) => {
444
+ UnusedSpanResult :: PartialUnused { spans, remove } => {
429
445
for fix in & remove {
430
446
fixes. push ( ( * fix, String :: new ( ) ) ) ;
431
447
}
0 commit comments