@@ -174,28 +174,30 @@ pub(crate) fn try_merge_trees(
174
174
let ( lhs_prefix, rhs_prefix) = common_prefix ( & lhs_path, & rhs_path) ?;
175
175
let lhs = lhs. split_prefix ( & lhs_prefix) ;
176
176
let rhs = rhs. split_prefix ( & rhs_prefix) ;
177
- recursive_merge ( & lhs, & rhs, merge) . map ( | ( merged , _ ) | merged )
177
+ recursive_merge ( & lhs, & rhs, merge)
178
178
}
179
179
180
180
/// Recursively "zips" together lhs and rhs.
181
181
fn recursive_merge (
182
182
lhs : & ast:: UseTree ,
183
183
rhs : & ast:: UseTree ,
184
184
merge : MergeBehaviour ,
185
- ) -> Option < ( ast:: UseTree , bool ) > {
185
+ ) -> Option < ast:: UseTree > {
186
186
let mut use_trees = lhs
187
187
. use_tree_list ( )
188
188
. into_iter ( )
189
189
. 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 ,
195
194
} )
196
195
. collect :: < Option < Vec < _ > > > ( ) ?;
197
196
use_trees. sort_unstable_by ( |a, b| path_cmp_opt ( a. path ( ) , b. path ( ) ) ) ;
198
197
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
+ }
199
201
let rhs_path = rhs_t. path ( ) ;
200
202
match use_trees. binary_search_by ( |p| path_cmp_opt ( p. path ( ) , rhs_path. clone ( ) ) ) {
201
203
Ok ( idx) => {
@@ -239,17 +241,9 @@ fn recursive_merge(
239
241
}
240
242
let lhs = lhs_t. split_prefix ( & lhs_prefix) ;
241
243
let rhs = rhs_t. split_prefix ( & rhs_prefix) ;
242
- let this_has_children = use_trees. len ( ) > 0 ;
243
244
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 ,
253
247
}
254
248
}
255
249
Err ( _)
@@ -264,8 +258,7 @@ fn recursive_merge(
264
258
}
265
259
}
266
260
}
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) ) )
269
262
}
270
263
271
264
/// 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
308
301
successors ( first_segment ( path) , |p| p. parent_path ( ) . parent_path ( ) . and_then ( |p| p. segment ( ) ) )
309
302
}
310
303
304
+ fn path_len ( path : ast:: Path ) -> usize {
305
+ segment_iter ( & path) . count ( )
306
+ }
307
+
311
308
/// Orders paths in the following way:
312
309
/// the sole self token comes first, after that come uppercase identifiers, then lowercase identifiers
313
310
// 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 {
352
349
Last ,
353
350
}
354
351
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
+
355
365
#[ derive( Eq , PartialEq , PartialOrd , Ord ) ]
356
366
enum ImportGroup {
357
367
// the order here defines the order of new group inserts
@@ -675,6 +685,11 @@ use std::io;",
675
685
)
676
686
}
677
687
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
+
678
693
#[ test]
679
694
fn merge_groups_full ( ) {
680
695
check_full (
@@ -819,8 +834,24 @@ use std::io;",
819
834
}
820
835
821
836
#[ 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
+ ) ;
824
855
}
825
856
826
857
#[ test]
0 commit comments