@@ -138,6 +138,29 @@ impl UseSegment {
138138 }
139139 }
140140
141+ // Check if self == other with their aliases removed.
142+ fn equal_except_alias ( & self , other : & Self ) -> bool {
143+ match ( self , other) {
144+ ( UseSegment :: Ident ( ref s1, _) , UseSegment :: Ident ( ref s2, _) ) => s1 == s2,
145+ ( UseSegment :: Slf ( _) , UseSegment :: Slf ( _) )
146+ | ( UseSegment :: Super ( _) , UseSegment :: Super ( _) )
147+ | ( UseSegment :: Crate ( _) , UseSegment :: Crate ( _) )
148+ | ( UseSegment :: Glob , UseSegment :: Glob ) => true ,
149+ ( UseSegment :: List ( ref list1) , UseSegment :: List ( ref list2) ) => list1 == list2,
150+ _ => false ,
151+ }
152+ }
153+
154+ fn get_alias ( & self ) -> Option < & str > {
155+ match self {
156+ UseSegment :: Ident ( _, a)
157+ | UseSegment :: Slf ( a)
158+ | UseSegment :: Super ( a)
159+ | UseSegment :: Crate ( a) => a. as_deref ( ) ,
160+ _ => None ,
161+ }
162+ }
163+
141164 fn from_path_segment (
142165 context : & RewriteContext < ' _ > ,
143166 path_seg : & ast:: PathSegment ,
@@ -558,6 +581,7 @@ impl UseTree {
558581 SharedPrefix :: Module => {
559582 self . path [ ..self . path . len ( ) - 1 ] == other. path [ ..other. path . len ( ) - 1 ]
560583 }
584+ SharedPrefix :: One => true ,
561585 }
562586 }
563587 }
@@ -598,7 +622,7 @@ impl UseTree {
598622 fn merge ( & mut self , other : & UseTree , merge_by : SharedPrefix ) {
599623 let mut prefix = 0 ;
600624 for ( a, b) in self . path . iter ( ) . zip ( other. path . iter ( ) ) {
601- if * a == * b {
625+ if a . equal_except_alias ( b ) {
602626 prefix += 1 ;
603627 } else {
604628 break ;
@@ -633,14 +657,20 @@ fn merge_rest(
633657 return Some ( new_path) ;
634658 }
635659 } else if len == 1 {
636- let rest = if a. len ( ) == len { & b[ 1 ..] } else { & a[ 1 ..] } ;
637- return Some ( vec ! [
638- b[ 0 ] . clone( ) ,
639- UseSegment :: List ( vec![
640- UseTree :: from_path( vec![ UseSegment :: Slf ( None ) ] , DUMMY_SP ) ,
641- UseTree :: from_path( rest. to_vec( ) , DUMMY_SP ) ,
642- ] ) ,
643- ] ) ;
660+ let ( common, rest) = if a. len ( ) == len {
661+ ( & a[ 0 ] , & b[ 1 ..] )
662+ } else {
663+ ( & b[ 0 ] , & a[ 1 ..] )
664+ } ;
665+ let mut list = vec ! [ UseTree :: from_path(
666+ vec![ UseSegment :: Slf ( common. get_alias( ) . map( ToString :: to_string) ) ] ,
667+ DUMMY_SP ,
668+ ) ] ;
669+ match rest {
670+ [ UseSegment :: List ( rest_list) ] => list. extend ( rest_list. clone ( ) ) ,
671+ _ => list. push ( UseTree :: from_path ( rest. to_vec ( ) , DUMMY_SP ) ) ,
672+ }
673+ return Some ( vec ! [ b[ 0 ] . clone( ) , UseSegment :: List ( list) ] ) ;
644674 } else {
645675 len -= 1 ;
646676 }
@@ -655,18 +685,54 @@ fn merge_rest(
655685}
656686
657687fn merge_use_trees_inner ( trees : & mut Vec < UseTree > , use_tree : UseTree , merge_by : SharedPrefix ) {
658- let similar_trees = trees
659- . iter_mut ( )
660- . filter ( |tree| tree. share_prefix ( & use_tree, merge_by) ) ;
688+ struct SimilarTree < ' a > {
689+ similarity : usize ,
690+ path_len : usize ,
691+ tree : & ' a mut UseTree ,
692+ }
693+
694+ let similar_trees = trees. iter_mut ( ) . filter_map ( |tree| {
695+ if tree. share_prefix ( & use_tree, merge_by) {
696+ // In the case of `SharedPrefix::One`, `similarity` is used for deciding with which
697+ // tree `use_tree` should be merge.
698+ // In other cases `similarity` won't be used, so set it to `0` as a dummy value.
699+ let similarity = if merge_by == SharedPrefix :: One {
700+ tree. path
701+ . iter ( )
702+ . zip ( & use_tree. path )
703+ . take_while ( |( a, b) | a. equal_except_alias ( b) )
704+ . count ( )
705+ } else {
706+ 0
707+ } ;
708+
709+ let path_len = tree. path . len ( ) ;
710+ Some ( SimilarTree {
711+ similarity,
712+ tree,
713+ path_len,
714+ } )
715+ } else {
716+ None
717+ }
718+ } ) ;
719+
661720 if use_tree. path . len ( ) == 1 && merge_by == SharedPrefix :: Crate {
662- if let Some ( tree) = similar_trees. min_by_key ( |tree| tree. path . len ( ) ) {
663- if tree. path . len ( ) == 1 {
721+ if let Some ( tree) = similar_trees. min_by_key ( |tree| tree. path_len ) {
722+ if tree. path_len == 1 {
723+ return ;
724+ }
725+ }
726+ } else if merge_by == SharedPrefix :: One {
727+ if let Some ( sim_tree) = similar_trees. max_by_key ( |tree| tree. similarity ) {
728+ if sim_tree. similarity > 0 {
729+ sim_tree. tree . merge ( & use_tree, merge_by) ;
664730 return ;
665731 }
666732 }
667- } else if let Some ( tree ) = similar_trees. max_by_key ( |tree| tree. path . len ( ) ) {
668- if tree . path . len ( ) > 1 {
669- tree. merge ( & use_tree, merge_by) ;
733+ } else if let Some ( sim_tree ) = similar_trees. max_by_key ( |tree| tree. path_len ) {
734+ if sim_tree . path_len > 1 {
735+ sim_tree . tree . merge ( & use_tree, merge_by) ;
670736 return ;
671737 }
672738 }
@@ -880,6 +946,7 @@ impl Rewrite for UseTree {
880946pub ( crate ) enum SharedPrefix {
881947 Crate ,
882948 Module ,
949+ One ,
883950}
884951
885952#[ cfg( test) ]
@@ -904,7 +971,7 @@ mod test {
904971 }
905972
906973 fn eat ( & mut self , c : char ) {
907- assert ! ( self . input. next( ) . unwrap( ) == c) ;
974+ assert_eq ! ( self . input. next( ) . unwrap( ) , c) ;
908975 }
909976
910977 fn push_segment (
@@ -1094,6 +1161,49 @@ mod test {
10941161 ) ;
10951162 }
10961163
1164+ #[ test]
1165+ fn test_use_tree_merge_one ( ) {
1166+ test_merge ! ( One , [ "a" , "b" ] , [ "{a, b}" ] ) ;
1167+
1168+ test_merge ! ( One , [ "a::{aa, ab}" , "b" , "a" ] , [ "{a::{self, aa, ab}, b}" ] ) ;
1169+
1170+ test_merge ! ( One , [ "a as x" , "b as y" ] , [ "{a as x, b as y}" ] ) ;
1171+
1172+ test_merge ! (
1173+ One ,
1174+ [ "a::{aa as xa, ab}" , "b" , "a" ] ,
1175+ [ "{a::{self, aa as xa, ab}, b}" ]
1176+ ) ;
1177+
1178+ test_merge ! (
1179+ One ,
1180+ [ "a" , "a::{aa, ab::{aba, abb}}" ] ,
1181+ [ "a::{self, aa, ab::{aba, abb}}" ]
1182+ ) ;
1183+
1184+ test_merge ! ( One , [ "a" , "b::{ba, *}" ] , [ "{a, b::{ba, *}}" ] ) ;
1185+
1186+ test_merge ! ( One , [ "a" , "b" , "a::aa" ] , [ "{a::{self, aa}, b}" ] ) ;
1187+
1188+ test_merge ! (
1189+ One ,
1190+ [ "a::aa::aaa" , "a::ac::aca" , "a::aa::*" ] ,
1191+ [ "a::{aa::{aaa, *}, ac::aca}" ]
1192+ ) ;
1193+
1194+ test_merge ! (
1195+ One ,
1196+ [ "a" , "b::{ba, bb}" , "a::{aa::*, ab::aba}" ] ,
1197+ [ "{a::{self, aa::*, ab::aba}, b::{ba, bb}}" ]
1198+ ) ;
1199+
1200+ test_merge ! (
1201+ One ,
1202+ [ "b" , "a::ac::{aca, acb}" , "a::{aa::*, ab}" ] ,
1203+ [ "{a::{aa::*, ab, ac::{aca, acb}}, b}" ]
1204+ ) ;
1205+ }
1206+
10971207 #[ test]
10981208 fn test_flatten_use_trees ( ) {
10991209 assert_eq ! (
0 commit comments