9
9
use std:: { fmt, mem, ops, panic:: RefUnwindSafe , str:: FromStr , sync:: Arc } ;
10
10
11
11
use cfg:: CfgOptions ;
12
- use la_arena:: { Arena , Idx , RawIdx } ;
12
+ use la_arena:: { Arena , Idx } ;
13
13
use rustc_hash:: { FxHashMap , FxHashSet } ;
14
14
use syntax:: SmolStr ;
15
15
use tt:: token_id:: Subtree ;
@@ -534,28 +534,46 @@ impl CrateGraph {
534
534
Some ( crate_id)
535
535
}
536
536
537
+ pub fn sort_deps ( & mut self ) {
538
+ self . arena
539
+ . iter_mut ( )
540
+ . for_each ( |( _, data) | data. dependencies . sort_by_key ( |dep| dep. crate_id ) ) ;
541
+ }
542
+
537
543
/// Extends this crate graph by adding a complete disjoint second crate
538
544
/// graph and adjust the ids in the [`ProcMacroPaths`] accordingly.
539
545
///
540
- /// The ids of the crates in the `other` graph are shifted by the return
541
- /// amount.
542
- pub fn extend ( & mut self , other : CrateGraph , proc_macros : & mut ProcMacroPaths ) -> u32 {
543
- let start = self . arena . len ( ) as u32 ;
544
- self . arena . extend ( other. arena . into_iter ( ) . map ( |( _, mut data) | {
545
- for dep in & mut data. dependencies {
546
- dep. crate_id =
547
- CrateId :: from_raw ( RawIdx :: from ( u32:: from ( dep. crate_id . into_raw ( ) ) + start) ) ;
546
+ /// This will deduplicate the crates of the graph where possible.
547
+ /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id.
548
+ /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted.
549
+ pub fn extend ( & mut self , mut other : CrateGraph , proc_macros : & mut ProcMacroPaths ) {
550
+ let topo = other. crates_in_topological_order ( ) ;
551
+ let mut id_map: FxHashMap < CrateId , CrateId > = FxHashMap :: default ( ) ;
552
+
553
+ for topo in topo {
554
+ let crate_data = & mut other. arena [ topo] ;
555
+ crate_data. dependencies . iter_mut ( ) . for_each ( |dep| dep. crate_id = id_map[ & dep. crate_id ] ) ;
556
+ crate_data. dependencies . sort_by_key ( |dep| dep. crate_id ) ;
557
+
558
+ let res = self . arena . iter ( ) . find_map (
559
+ |( id, data) | {
560
+ if data == crate_data {
561
+ Some ( id)
562
+ } else {
563
+ None
564
+ }
565
+ } ,
566
+ ) ;
567
+ if let Some ( res) = res {
568
+ id_map. insert ( topo, res) ;
569
+ } else {
570
+ let id = self . arena . alloc ( crate_data. clone ( ) ) ;
571
+ id_map. insert ( topo, id) ;
548
572
}
549
- data
550
- } ) ) ;
573
+ }
551
574
552
- * proc_macros = mem:: take ( proc_macros)
553
- . into_iter ( )
554
- . map ( |( id, macros) | {
555
- ( CrateId :: from_raw ( RawIdx :: from ( u32:: from ( id. into_raw ( ) ) + start) ) , macros)
556
- } )
557
- . collect ( ) ;
558
- start
575
+ * proc_macros =
576
+ mem:: take ( proc_macros) . into_iter ( ) . map ( |( id, macros) | ( id_map[ & id] , macros) ) . collect ( ) ;
559
577
}
560
578
561
579
fn find_path (
@@ -586,8 +604,10 @@ impl CrateGraph {
586
604
// Work around for https://github.com/rust-lang/rust-analyzer/issues/6038.
587
605
// As hacky as it gets.
588
606
pub fn patch_cfg_if ( & mut self ) -> bool {
589
- let cfg_if = self . hacky_find_crate ( "cfg_if" ) ;
590
- let std = self . hacky_find_crate ( "std" ) ;
607
+ // we stupidly max by version in an attempt to have all duplicated std's depend on the same cfg_if so that deduplication still works
608
+ let cfg_if =
609
+ self . hacky_find_crate ( "cfg_if" ) . max_by_key ( |& it| self . arena [ it] . version . clone ( ) ) ;
610
+ let std = self . hacky_find_crate ( "std" ) . next ( ) ;
591
611
match ( cfg_if, std) {
592
612
( Some ( cfg_if) , Some ( std) ) => {
593
613
self . arena [ cfg_if] . dependencies . clear ( ) ;
@@ -600,8 +620,8 @@ impl CrateGraph {
600
620
}
601
621
}
602
622
603
- fn hacky_find_crate ( & self , display_name : & str ) -> Option < CrateId > {
604
- self . iter ( ) . find ( |it| self [ * it] . display_name . as_deref ( ) == Some ( display_name) )
623
+ fn hacky_find_crate < ' a > ( & ' a self , display_name : & ' a str ) -> impl Iterator < Item = CrateId > + ' a {
624
+ self . iter ( ) . filter ( move |it| self [ * it] . display_name . as_deref ( ) == Some ( display_name) )
605
625
}
606
626
}
607
627
0 commit comments