@@ -413,7 +413,10 @@ impl Module {
413
413
ctx,
414
414
)
415
415
{
416
- import_paths_to_be_removed. push ( import_path) ;
416
+ check_intersection_and_push (
417
+ & mut import_paths_to_be_removed,
418
+ import_path,
419
+ ) ;
417
420
}
418
421
}
419
422
}
@@ -439,7 +442,10 @@ impl Module {
439
442
ctx,
440
443
)
441
444
{
442
- import_paths_to_be_removed. push ( import_path) ;
445
+ check_intersection_and_push (
446
+ & mut import_paths_to_be_removed,
447
+ import_path,
448
+ ) ;
443
449
}
444
450
}
445
451
}
@@ -543,12 +549,25 @@ impl Module {
543
549
} else if exists_inside_sel && !exists_outside_sel {
544
550
//Changes to be made inside new module, and remove import from outside
545
551
546
- if let Some ( ( use_tree_str, text_range_opt) ) =
552
+ if let Some ( ( mut use_tree_str, text_range_opt) ) =
547
553
self . process_use_stmt_for_import_resolve ( use_stmt_opt, node_syntax)
548
554
{
549
555
if let Some ( text_range) = text_range_opt {
550
556
import_path_to_be_removed = Some ( text_range) ;
551
557
}
558
+
559
+ if source_exists_outside_sel_in_same_mod {
560
+ if let Some ( first_path_in_use_tree) = use_tree_str. last ( ) {
561
+ let first_path_in_use_tree_str = first_path_in_use_tree. to_string ( ) ;
562
+ if !first_path_in_use_tree_str. contains ( "super" )
563
+ && !first_path_in_use_tree_str. contains ( "crate" )
564
+ {
565
+ let super_path = make:: ext:: ident_path ( "super" ) ;
566
+ use_tree_str. push ( super_path) ;
567
+ }
568
+ }
569
+ }
570
+
552
571
use_tree_str_opt = Some ( use_tree_str) ;
553
572
} else if source_exists_outside_sel_in_same_mod {
554
573
self . make_use_stmt_of_node_with_super ( node_syntax) ;
@@ -558,9 +577,16 @@ impl Module {
558
577
if let Some ( use_tree_str) = use_tree_str_opt {
559
578
let mut use_tree_str = use_tree_str;
560
579
use_tree_str. reverse ( ) ;
561
- if use_tree_str[ 0 ] . to_string ( ) . contains ( "super" ) {
562
- let super_path = make:: ext:: ident_path ( "super" ) ;
563
- use_tree_str. insert ( 0 , super_path)
580
+
581
+ if !( !exists_outside_sel && exists_inside_sel && source_exists_outside_sel_in_same_mod)
582
+ {
583
+ if let Some ( first_path_in_use_tree) = use_tree_str. first ( ) {
584
+ let first_path_in_use_tree_str = first_path_in_use_tree. to_string ( ) ;
585
+ if first_path_in_use_tree_str. contains ( "super" ) {
586
+ let super_path = make:: ext:: ident_path ( "super" ) ;
587
+ use_tree_str. insert ( 0 , super_path)
588
+ }
589
+ }
564
590
}
565
591
566
592
let use_ =
@@ -621,6 +647,32 @@ impl Module {
621
647
}
622
648
}
623
649
650
+ fn check_intersection_and_push (
651
+ import_paths_to_be_removed : & mut Vec < TextRange > ,
652
+ import_path : TextRange ,
653
+ ) {
654
+ if import_paths_to_be_removed. len ( ) > 0 {
655
+ // Text ranges recieved here for imports are extended to the
656
+ // next/previous comma which can cause intersections among them
657
+ // and later deletion of these can cause panics similar
658
+ // to reported in #11766. So to mitigate it, we
659
+ // check for intersection between all current members
660
+ // and if it exists we combine both text ranges into
661
+ // one
662
+ let r = import_paths_to_be_removed
663
+ . into_iter ( )
664
+ . position ( |it| it. intersect ( import_path) . is_some ( ) ) ;
665
+ match r {
666
+ Some ( it) => {
667
+ import_paths_to_be_removed[ it] = import_paths_to_be_removed[ it] . cover ( import_path)
668
+ }
669
+ None => import_paths_to_be_removed. push ( import_path) ,
670
+ }
671
+ } else {
672
+ import_paths_to_be_removed. push ( import_path) ;
673
+ }
674
+ }
675
+
624
676
fn does_source_exists_outside_sel_in_same_mod (
625
677
def : Definition ,
626
678
ctx : & AssistContext ,
@@ -1495,4 +1547,38 @@ mod modname {
1495
1547
" ,
1496
1548
)
1497
1549
}
1550
+
1551
+ #[ test]
1552
+ fn test_issue_11766 ( ) {
1553
+ //https://github.com/rust-lang/rust-analyzer/issues/11766
1554
+ check_assist (
1555
+ extract_module,
1556
+ r"
1557
+ mod x {
1558
+ pub struct Foo;
1559
+ pub struct Bar;
1560
+ }
1561
+
1562
+ use x::{Bar, Foo};
1563
+
1564
+ $0type A = (Foo, Bar);$0
1565
+ " ,
1566
+ r"
1567
+ mod x {
1568
+ pub struct Foo;
1569
+ pub struct Bar;
1570
+ }
1571
+
1572
+ use x::{};
1573
+
1574
+ mod modname {
1575
+ use super::x::Bar;
1576
+
1577
+ use super::x::Foo;
1578
+
1579
+ pub(crate) type A = (Foo, Bar);
1580
+ }
1581
+ " ,
1582
+ )
1583
+ }
1498
1584
}
0 commit comments