remove braces when fixing a nested use tree into a single use

This commit is contained in:
Pietro Albini 2024-04-14 18:40:49 +02:00
parent 13f76235b3
commit 2d3a9a5847
No known key found for this signature in database
GPG Key ID: 3E06ABE80BAAF19C
4 changed files with 135 additions and 1 deletions

View File

@ -292,7 +292,7 @@ fn calc_unused_spans(
UnusedSpanResult::Used
}
}
ast::UseTreeKind::Nested { items: ref nested, .. } => {
ast::UseTreeKind::Nested { items: ref nested, span: tree_span } => {
if nested.is_empty() {
return UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span };
}
@ -300,6 +300,7 @@ fn calc_unused_spans(
let mut unused_spans = Vec::new();
let mut to_remove = Vec::new();
let mut used_childs = 0;
let mut contains_self = false;
let mut previous_unused = false;
for (pos, (use_tree, use_tree_id)) in nested.iter().enumerate() {
let remove = match calc_unused_spans(unused_import, use_tree, *use_tree_id) {
@ -339,6 +340,8 @@ fn calc_unused_spans(
to_remove.push(remove_span);
}
}
contains_self |= use_tree.prefix == kw::SelfLower
&& matches!(use_tree.kind, ast::UseTreeKind::Simple(None));
previous_unused = remove.is_some();
}
if unused_spans.is_empty() {
@ -346,6 +349,28 @@ fn calc_unused_spans(
} else if used_childs == 0 {
UnusedSpanResult::Unused { spans: unused_spans, remove: full_span }
} else {
// If there is only one remaining child that is used, the braces around the use
// tree are not needed anymore. In that case, we determine the span of the left
// brace and the right brace, and tell rustfix to remove them as well.
//
// This means that `use a::{B, C};` will be turned into `use a::B;` rather than
// `use a::{B};`, removing a rustfmt roundtrip.
//
// Note that we cannot remove the braces if the only item inside the use tree is
// `self`: `use foo::{self};` is valid Rust syntax, while `use foo::self;` errors
// out. We also cannot turn `use foo::{self}` into `use foo`, as the former doesn't
// import types with the same name as the module.
if used_childs == 1 && !contains_self {
// Left brace, from the start of the nested group to the first item.
to_remove.push(
tree_span.shrink_to_lo().to(nested.first().unwrap().0.span.shrink_to_lo()),
);
// Right brace, from the end of the last item to the end of the nested group.
to_remove.push(
nested.last().unwrap().0.span.shrink_to_hi().to(tree_span.shrink_to_hi()),
);
}
UnusedSpanResult::PartialUnused { spans: unused_spans, remove: to_remove }
}
}

View File

@ -0,0 +1,35 @@
//@ run-rustfix
//@ check-pass
#![warn(unused_imports)]
pub mod nested {
pub struct A;
pub struct B;
pub struct C;
pub struct D;
pub mod even_more {
pub struct E;
pub struct F;
pub struct G;
}
pub mod another {
pub struct H;
pub struct I;
}
}
use nested::B;
//~^ WARN unused import
use nested::even_more::F;
//~^^^^^^^ WARN unused import
// Note that the following fix should result in `::{self}`, not `::self`. The latter is invalid
// Rust syntax, so the braces should not be removed.
use nested::another::{self};
//~^ WARN unused import
fn main() {
let _ = (B, F, another::I);
}

View File

@ -0,0 +1,42 @@
//@ run-rustfix
//@ check-pass
#![warn(unused_imports)]
pub mod nested {
pub struct A;
pub struct B;
pub struct C;
pub struct D;
pub mod even_more {
pub struct E;
pub struct F;
pub struct G;
}
pub mod another {
pub struct H;
pub struct I;
}
}
use nested::{A, B, C};
//~^ WARN unused import
use nested::{
D,
even_more::{
E,
F,
G,
},
};
//~^^^^^^^ WARN unused import
// Note that the following fix should result in `::{self}`, not `::self`. The latter is invalid
// Rust syntax, so the braces should not be removed.
use nested::another::{self, I};
//~^ WARN unused import
fn main() {
let _ = (B, F, another::I);
}

View File

@ -0,0 +1,32 @@
warning: unused imports: `A`, `C`
--> $DIR/unused-imports.rs:22:14
|
LL | use nested::{A, B, C};
| ^ ^
|
note: the lint level is defined here
--> $DIR/unused-imports.rs:4:9
|
LL | #![warn(unused_imports)]
| ^^^^^^^^^^^^^^
warning: unused imports: `D`, `E`, `G`
--> $DIR/unused-imports.rs:26:5
|
LL | D,
| ^
LL | even_more::{
LL | E,
| ^
LL | F,
LL | G,
| ^
warning: unused import: `I`
--> $DIR/unused-imports.rs:37:29
|
LL | use nested::another::{self, I};
| ^
warning: 3 warnings emitted