@@ -174,28 +174,30 @@ pub(crate) fn try_merge_trees(
174174 let ( lhs_prefix, rhs_prefix) = common_prefix ( & lhs_path, & rhs_path) ?;
175175 let lhs = lhs. split_prefix ( & lhs_prefix) ;
176176 let rhs = rhs. split_prefix ( & rhs_prefix) ;
177- recursive_merge ( & lhs, & rhs, merge) . map ( | ( merged , _ ) | merged )
177+ recursive_merge ( & lhs, & rhs, merge)
178178}
179179
180180/// Recursively "zips" together lhs and rhs.
181181fn recursive_merge (
182182 lhs : & ast:: UseTree ,
183183 rhs : & ast:: UseTree ,
184184 merge : MergeBehaviour ,
185- ) -> Option < ( ast:: UseTree , bool ) > {
185+ ) -> Option < ast:: UseTree > {
186186 let mut use_trees = lhs
187187 . use_tree_list ( )
188188 . into_iter ( )
189189 . flat_map ( |list| list. use_trees ( ) )
190- // check if any of the use trees are nested, if they are and the behaviour is `last` we are not allowed to merge this
191- // so early exit the iterator by using Option's Intoiterator impl
192- . map ( |tree| match merge == MergeBehaviour :: Last && tree. use_tree_list ( ) . is_some ( ) {
193- true => None ,
194- false => Some ( tree) ,
190+ // we use Option here to early return from this function(this is not the same as a `filter` op)
191+ . map ( |tree| match merge. is_tree_allowed ( & tree) {
192+ true => Some ( tree) ,
193+ false => None ,
195194 } )
196195 . collect :: < Option < Vec < _ > > > ( ) ?;
197196 use_trees. sort_unstable_by ( |a, b| path_cmp_opt ( a. path ( ) , b. path ( ) ) ) ;
198197 for rhs_t in rhs. use_tree_list ( ) . into_iter ( ) . flat_map ( |list| list. use_trees ( ) ) {
198+ if !merge. is_tree_allowed ( & rhs_t) {
199+ return None ;
200+ }
199201 let rhs_path = rhs_t. path ( ) ;
200202 match use_trees. binary_search_by ( |p| path_cmp_opt ( p. path ( ) , rhs_path. clone ( ) ) ) {
201203 Ok ( idx) => {
@@ -239,17 +241,9 @@ fn recursive_merge(
239241 }
240242 let lhs = lhs_t. split_prefix ( & lhs_prefix) ;
241243 let rhs = rhs_t. split_prefix ( & rhs_prefix) ;
242- let this_has_children = use_trees. len ( ) > 0 ;
243244 match recursive_merge ( & lhs, & rhs, merge) {
244- Some ( ( _, has_multiple_children) )
245- if merge == MergeBehaviour :: Last
246- && this_has_children
247- && has_multiple_children =>
248- {
249- return None
250- }
251- Some ( ( use_tree, _) ) => use_trees[ idx] = use_tree,
252- None => use_trees. insert ( idx, rhs_t) ,
245+ Some ( use_tree) => use_trees[ idx] = use_tree,
246+ None => return None ,
253247 }
254248 }
255249 Err ( _)
@@ -264,8 +258,7 @@ fn recursive_merge(
264258 }
265259 }
266260 }
267- let has_multiple_children = use_trees. len ( ) > 1 ;
268- Some ( ( lhs. with_use_tree_list ( make:: use_tree_list ( use_trees) ) , has_multiple_children) )
261+ Some ( lhs. with_use_tree_list ( make:: use_tree_list ( use_trees) ) )
269262}
270263
271264/// Traverses both paths until they differ, returning the common prefix of both.
@@ -308,6 +301,10 @@ fn segment_iter(path: &ast::Path) -> impl Iterator<Item = ast::PathSegment> + Cl
308301 successors ( first_segment ( path) , |p| p. parent_path ( ) . parent_path ( ) . and_then ( |p| p. segment ( ) ) )
309302}
310303
304+ fn path_len ( path : ast:: Path ) -> usize {
305+ segment_iter ( & path) . count ( )
306+ }
307+
311308/// Orders paths in the following way:
312309/// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers
313310// FIXME: rustfmt sort lowercase idents before uppercase, in general we want to have the same ordering rustfmt has
@@ -352,6 +349,19 @@ pub enum MergeBehaviour {
352349 Last ,
353350}
354351
352+ impl MergeBehaviour {
353+ #[ inline]
354+ fn is_tree_allowed ( & self , tree : & ast:: UseTree ) -> bool {
355+ match self {
356+ MergeBehaviour :: Full => true ,
357+ // only simple single segment paths are allowed
358+ MergeBehaviour :: Last => {
359+ tree. use_tree_list ( ) . is_none ( ) && tree. path ( ) . map ( path_len) <= Some ( 1 )
360+ }
361+ }
362+ }
363+ }
364+
355365#[ derive( Eq , PartialEq , PartialOrd , Ord ) ]
356366enum ImportGroup {
357367 // the order here defines the order of new group inserts
@@ -675,6 +685,11 @@ use std::io;",
675685 )
676686 }
677687
688+ #[ test]
689+ fn merge_last_into_self ( ) {
690+ check_last ( "foo::bar::baz" , r"use foo::bar;" , r"use foo::bar::{self, baz};" ) ;
691+ }
692+
678693 #[ test]
679694 fn merge_groups_full ( ) {
680695 check_full (
@@ -819,8 +834,24 @@ use std::io;",
819834 }
820835
821836 #[ test]
822- fn merge_last_too_long ( ) {
823- check_last ( "foo::bar" , r"use foo::bar::baz::Qux;" , r"use foo::bar::{self, baz::Qux};" ) ;
837+ fn skip_merge_last_too_long ( ) {
838+ check_last (
839+ "foo::bar" ,
840+ r"use foo::bar::baz::Qux;" ,
841+ r"use foo::bar;
842+ use foo::bar::baz::Qux;" ,
843+ ) ;
844+ }
845+
846+ #[ test]
847+ #[ ignore] // FIXME: Order changes when switching lhs and rhs
848+ fn skip_merge_last_too_long2 ( ) {
849+ check_last (
850+ "foo::bar::baz::Qux" ,
851+ r"use foo::bar;" ,
852+ r"use foo::bar;
853+ use foo::bar::baz::Qux;" ,
854+ ) ;
824855 }
825856
826857 #[ test]
0 commit comments