1- use std:: borrow:: Cow ;
21use std:: cmp:: Ordering ;
32use std:: fmt;
3+ use std:: { borrow:: Cow , vec} ;
44
55use core:: hash:: { Hash , Hasher } ;
66
@@ -130,7 +130,13 @@ pub(crate) struct UseTree {
130130
131131impl PartialEq for UseTree {
132132 fn eq ( & self , other : & UseTree ) -> bool {
133+ // We bail out attributes because we cannot safely merge attributes.
134+ // We bail out comments because we cannot safely merge comments.
133135 self . path == other. path
136+ && !self . has_attrs ( )
137+ && !other. has_attrs ( )
138+ && !self . has_comment ( )
139+ && !other. has_comment ( )
134140 }
135141}
136142impl Eq for UseTree { }
@@ -233,13 +239,19 @@ pub(crate) fn normalize_use_trees_with_granularity(
233239
234240 let mut result = Vec :: with_capacity ( use_trees. len ( ) ) ;
235241 for use_tree in use_trees {
236- if use_tree. contains_comment ( ) || use_tree. attrs . is_some ( ) {
242+ if use_tree. contains_comment ( ) || use_tree. has_attrs_disallow_outer_style ( ) {
237243 result. push ( use_tree) ;
238244 continue ;
239245 }
246+ let attrs = use_tree. attrs . clone ( ) ;
247+ let result_buf = if attrs. is_some ( ) {
248+ & mut vec ! [ ]
249+ } else {
250+ & mut result
251+ } ;
240252
241253 for mut flattened in use_tree. flatten ( import_granularity) {
242- if let Some ( tree) = result
254+ if let Some ( tree) = result_buf
243255 . iter_mut ( )
244256 . find ( |tree| tree. share_prefix ( & flattened, merge_by) )
245257 {
@@ -249,9 +261,19 @@ pub(crate) fn normalize_use_trees_with_granularity(
249261 if merge_by == SharedPrefix :: Module {
250262 flattened = flattened. nest_trailing_self ( ) ;
251263 }
252- result . push ( flattened) ;
264+ result_buf . push ( flattened) ;
253265 }
254266 }
267+ if let Some ( attrs) = attrs {
268+ let result_buf: Vec < _ > = result_buf
269+ . drain ( ..)
270+ . map ( |mut use_tree| {
271+ use_tree. attrs = Some ( attrs. clone ( ) ) ;
272+ use_tree
273+ } )
274+ . collect ( ) ;
275+ result. extend ( result_buf) ;
276+ }
255277 }
256278 result
257279}
@@ -386,11 +408,11 @@ impl UseTree {
386408 // use-statements. This should not be a problem, though, since we have
387409 // already tried to extract comment and observed that there are no comment
388410 // around the given use item, and the span will not be used afterward.
389- fn from_path ( path : Vec < UseSegment > , span : Span ) -> UseTree {
411+ fn from_path ( path : Vec < UseSegment > , span : Span , list_item : Option < ListItem > ) -> UseTree {
390412 UseTree {
391413 path,
392414 span,
393- list_item : None ,
415+ list_item,
394416 visibility : None ,
395417 attrs : None ,
396418 }
@@ -559,7 +581,7 @@ impl UseTree {
559581
560582 // Remove foo::{} or self without attributes.
561583 match last. kind {
562- _ if self . attrs . is_some ( ) => ( ) ,
584+ _ if self . has_attrs ( ) => ( ) ,
563585 UseSegmentKind :: List ( ref list) if list. is_empty ( ) => {
564586 self . path = vec ! [ ] ;
565587 return self ;
@@ -657,6 +679,17 @@ impl UseTree {
657679 self . has_comment ( ) || self . path . iter ( ) . any ( |path| path. contains_comment ( ) )
658680 }
659681
682+ fn has_attrs ( & self ) -> bool {
683+ self . attrs . is_some ( )
684+ }
685+
686+ fn has_attrs_disallow_outer_style ( & self ) -> bool {
687+ !self . attrs . iter ( ) . flatten ( ) . all ( |attr| match & attr. kind {
688+ ast:: AttrKind :: Normal ( attr) => attr. item . is_valid_for_outer_style ( ) ,
689+ ast:: AttrKind :: DocComment ( ..) => false ,
690+ } )
691+ }
692+
660693 fn same_visibility ( & self , other : & UseTree ) -> bool {
661694 match ( & self . visibility , & other. visibility ) {
662695 (
@@ -682,7 +715,8 @@ impl UseTree {
682715 fn share_prefix ( & self , other : & UseTree , shared_prefix : SharedPrefix ) -> bool {
683716 if self . path . is_empty ( )
684717 || other. path . is_empty ( )
685- || self . attrs . is_some ( )
718+ || self . has_attrs ( )
719+ || other. has_attrs ( )
686720 || self . contains_comment ( )
687721 || !self . same_visibility ( other)
688722 {
@@ -696,8 +730,10 @@ impl UseTree {
696730 }
697731 }
698732
733+ /// The main tree-flattening process.
699734 fn flatten ( self , import_granularity : ImportGranularity ) -> Vec < UseTree > {
700- if self . path . is_empty ( ) || self . contains_comment ( ) {
735+ if self . path . is_empty ( ) || self . contains_comment ( ) || self . has_attrs_disallow_outer_style ( )
736+ {
701737 return vec ! [ self ] ;
702738 }
703739 match & self . path . clone ( ) . last ( ) . unwrap ( ) . kind {
@@ -716,7 +752,7 @@ impl UseTree {
716752 result. push ( UseTree {
717753 path : new_path,
718754 span : self . span ,
719- list_item : None ,
755+ list_item : flattened . list_item . clone ( ) ,
720756 visibility : self . visibility . clone ( ) ,
721757 // only retain attributes for `ImportGranularity::Item`
722758 attrs : match import_granularity {
@@ -758,7 +794,11 @@ impl UseTree {
758794 {
759795 let self_segment = self . path . pop ( ) . unwrap ( ) ;
760796 let style_edition = self_segment. style_edition ;
761- let kind = UseSegmentKind :: List ( vec ! [ UseTree :: from_path( vec![ self_segment] , DUMMY_SP ) ] ) ;
797+ let kind = UseSegmentKind :: List ( vec ! [ UseTree :: from_path(
798+ vec![ self_segment] ,
799+ DUMMY_SP ,
800+ self . list_item. clone( ) ,
801+ ) ] ) ;
762802 self . path . push ( UseSegment {
763803 kind,
764804 style_edition,
@@ -783,7 +823,7 @@ fn merge_rest(
783823 let mut list = list. clone ( ) ;
784824 merge_use_trees_inner (
785825 & mut list,
786- UseTree :: from_path ( b[ len..] . to_vec ( ) , DUMMY_SP ) ,
826+ UseTree :: from_path ( b[ len..] . to_vec ( ) , DUMMY_SP , None ) ,
787827 merge_by,
788828 ) ;
789829 let mut new_path = b[ ..len] . to_vec ( ) ;
@@ -808,6 +848,7 @@ fn merge_rest(
808848 style_edition,
809849 } ] ,
810850 DUMMY_SP ,
851+ None ,
811852 ) ] ;
812853 match rest {
813854 [
@@ -816,7 +857,7 @@ fn merge_rest(
816857 ..
817858 } ,
818859 ] => list. extend ( rest_list. clone ( ) ) ,
819- _ => list. push ( UseTree :: from_path ( rest. to_vec ( ) , DUMMY_SP ) ) ,
860+ _ => list. push ( UseTree :: from_path ( rest. to_vec ( ) , DUMMY_SP , None ) ) ,
820861 }
821862 return Some ( vec ! [
822863 b[ 0 ] . clone( ) ,
@@ -829,8 +870,8 @@ fn merge_rest(
829870 len -= 1 ;
830871 }
831872 let mut list = vec ! [
832- UseTree :: from_path( a[ len..] . to_vec( ) , DUMMY_SP ) ,
833- UseTree :: from_path( b[ len..] . to_vec( ) , DUMMY_SP ) ,
873+ UseTree :: from_path( a[ len..] . to_vec( ) , DUMMY_SP , None ) ,
874+ UseTree :: from_path( b[ len..] . to_vec( ) , DUMMY_SP , None ) ,
834875 ] ;
835876 list. sort ( ) ;
836877 list. dedup ( ) ;
0 commit comments