diff --git a/src/imports.rs b/src/imports.rs index f0797516b15..e3a0086ebb1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -1,6 +1,6 @@ -use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; +use std::{borrow::Cow, vec}; use core::hash::{Hash, Hasher}; @@ -212,6 +212,15 @@ impl UseSegment { } } +fn attrs_disallow_outer_style(attrs: &ast::AttrVec) -> bool { + !attrs.iter().all(|attr| { + let ast::AttrKind::Normal(attr) = &attr.kind else { + return false; + }; + attr.item.is_valid_for_outer_style() + }) +} + pub(crate) fn normalize_use_trees_with_granularity( use_trees: Vec, import_granularity: ImportGranularity, @@ -226,13 +235,24 @@ pub(crate) fn normalize_use_trees_with_granularity( let mut result = Vec::with_capacity(use_trees.len()); for use_tree in use_trees { - if use_tree.contains_comment() || use_tree.attrs.is_some() { + if use_tree.contains_comment() + || use_tree + .attrs + .as_ref() + .map_or(false, attrs_disallow_outer_style) + { result.push(use_tree); continue; } + let attrs = use_tree.attrs.clone(); + let result_buf = if attrs.is_some() { + &mut vec![] + } else { + &mut result + }; for mut flattened in use_tree.flatten(import_granularity) { - if let Some(tree) = result + if let Some(tree) = result_buf .iter_mut() .find(|tree| tree.share_prefix(&flattened, merge_by)) { @@ -242,9 +262,19 @@ pub(crate) fn normalize_use_trees_with_granularity( if merge_by == SharedPrefix::Module { flattened = flattened.nest_trailing_self(); } - result.push(flattened); + result_buf.push(flattened); } } + if let Some(attrs) = attrs { + let result_buf: Vec<_> = result_buf + .drain(..) + .map(|mut use_tree| { + use_tree.attrs = Some(attrs.clone()); + use_tree + }) + .collect(); + result.extend(result_buf); + } } result } diff --git a/tests/source/imports/imports_granularity_crate.rs b/tests/source/imports/imports_granularity_crate.rs index f6f7761e82e..2beaef40761 100644 --- a/tests/source/imports/imports_granularity_crate.rs +++ b/tests/source/imports/imports_granularity_crate.rs @@ -63,3 +63,7 @@ use b::v::{ }; use b::t::{/* Before b::t::self */ self}; use b::c; + +// https://github.com/rust-lang/rustfmt/issues/6666 +#[cfg(true)] +use a::{b::c, d::e, d::f}; diff --git a/tests/target/imports/imports_granularity_crate.rs b/tests/target/imports/imports_granularity_crate.rs index 36e01558ff0..3ff72d97b53 100644 --- a/tests/target/imports/imports_granularity_crate.rs +++ b/tests/target/imports/imports_granularity_crate.rs @@ -57,3 +57,10 @@ use b::{ /* Before b::l group */ l::{self, m, n::o, p::*}, q, }; + +// https://github.com/rust-lang/rustfmt/issues/6666 +#[cfg(true)] +use a::{ + b::c, + d::{e, f}, +}; diff --git a/tests/target/imports/imports_granularity_module.rs b/tests/target/imports/imports_granularity_module.rs index 14f341016ff..286afce2920 100644 --- a/tests/target/imports/imports_granularity_module.rs +++ b/tests/target/imports/imports_granularity_module.rs @@ -13,9 +13,11 @@ pub use a::t; use b::c::d; use b::{self}; -use foo::e; #[cfg(test)] -use foo::{a::b, c::d}; +use foo::a::b; +#[cfg(test)] +use foo::c::d; +use foo::e; use bar::{ // comment