99use std:: { fmt, mem, ops, str:: FromStr } ;
1010
1111use cfg:: CfgOptions ;
12- use la_arena:: { Arena , Idx } ;
12+ use la_arena:: { Arena , Idx , RawIdx } ;
1313use rustc_hash:: { FxHashMap , FxHashSet } ;
1414use semver:: Version ;
1515use syntax:: SmolStr ;
@@ -157,6 +157,10 @@ impl CrateOrigin {
157157 pub fn is_lib ( & self ) -> bool {
158158 matches ! ( self , CrateOrigin :: Library { .. } )
159159 }
160+
161+ pub fn is_lang ( & self ) -> bool {
162+ matches ! ( self , CrateOrigin :: Lang { .. } )
163+ }
160164}
161165
162166#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -174,7 +178,7 @@ impl From<&str> for LangCrateOrigin {
174178 match s {
175179 "alloc" => LangCrateOrigin :: Alloc ,
176180 "core" => LangCrateOrigin :: Core ,
177- "proc-macro" => LangCrateOrigin :: ProcMacro ,
181+ "proc-macro" | "proc_macro" => LangCrateOrigin :: ProcMacro ,
178182 "std" => LangCrateOrigin :: Std ,
179183 "test" => LangCrateOrigin :: Test ,
180184 _ => LangCrateOrigin :: Other ,
@@ -257,6 +261,7 @@ impl ReleaseChannel {
257261 }
258262 }
259263
264+ #[ allow( clippy:: should_implement_trait) ]
260265 pub fn from_str ( str : & str ) -> Option < Self > {
261266 Some ( match str {
262267 "" | "stable" => ReleaseChannel :: Stable ,
@@ -326,7 +331,7 @@ impl CrateData {
326331 return false ;
327332 }
328333
329- if let Some ( _ ) = opts. next ( ) {
334+ if opts. next ( ) . is_some ( ) {
330335 return false ;
331336 }
332337 }
@@ -522,7 +527,7 @@ impl CrateGraph {
522527 self . arena . iter ( ) . map ( |( idx, _) | idx)
523528 }
524529
525- // FIXME: used for `handle_hack_cargo_workspace` , should be removed later
530+ // FIXME: used for fixing up the toolchain sysroot , should be removed and done differently
526531 #[ doc( hidden) ]
527532 pub fn iter_mut ( & mut self ) -> impl Iterator < Item = ( CrateId , & mut CrateData ) > + ' _ {
528533 self . arena . iter_mut ( )
@@ -619,7 +624,12 @@ impl CrateGraph {
619624 /// This will deduplicate the crates of the graph where possible.
620625 /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id.
621626 /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted.
622- pub fn extend ( & mut self , mut other : CrateGraph , proc_macros : & mut ProcMacroPaths ) {
627+ pub fn extend (
628+ & mut self ,
629+ mut other : CrateGraph ,
630+ proc_macros : & mut ProcMacroPaths ,
631+ on_finished : impl FnOnce ( & FxHashMap < CrateId , CrateId > ) ,
632+ ) {
623633 let topo = other. crates_in_topological_order ( ) ;
624634 let mut id_map: FxHashMap < CrateId , CrateId > = FxHashMap :: default ( ) ;
625635 for topo in topo {
@@ -630,7 +640,7 @@ impl CrateGraph {
630640 let res = self . arena . iter ( ) . find_map ( |( id, data) | {
631641 match ( & data. origin , & crate_data. origin ) {
632642 ( a, b) if a == b => {
633- if data. eq_ignoring_origin_and_deps ( & crate_data, false ) {
643+ if data. eq_ignoring_origin_and_deps ( crate_data, false ) {
634644 return Some ( ( id, false ) ) ;
635645 }
636646 }
@@ -642,8 +652,8 @@ impl CrateGraph {
642652 // version and discard the library one as the local version may have
643653 // dev-dependencies that we want to keep resolving. See #15656 for more
644654 // information.
645- if data. eq_ignoring_origin_and_deps ( & crate_data, true ) {
646- return Some ( ( id, if a. is_local ( ) { false } else { true } ) ) ;
655+ if data. eq_ignoring_origin_and_deps ( crate_data, true ) {
656+ return Some ( ( id, ! a. is_local ( ) ) ) ;
647657 }
648658 }
649659 ( _, _) => return None ,
@@ -670,6 +680,8 @@ impl CrateGraph {
670680
671681 * proc_macros =
672682 mem:: take ( proc_macros) . into_iter ( ) . map ( |( id, macros) | ( id_map[ & id] , macros) ) . collect ( ) ;
683+
684+ on_finished ( & id_map) ;
673685 }
674686
675687 fn find_path (
@@ -721,6 +733,29 @@ impl CrateGraph {
721733 fn hacky_find_crate < ' a > ( & ' a self , display_name : & ' a str ) -> impl Iterator < Item = CrateId > + ' a {
722734 self . iter ( ) . filter ( move |it| self [ * it] . display_name . as_deref ( ) == Some ( display_name) )
723735 }
736+
737+ /// Removes all crates from this crate graph except for the ones in `to_keep` and fixes up the dependencies.
738+ /// Returns a mapping from old crate ids to new crate ids.
739+ pub fn remove_crates_except ( & mut self , to_keep : & [ CrateId ] ) -> Vec < Option < CrateId > > {
740+ let mut id_map = vec ! [ None ; self . arena. len( ) ] ;
741+ self . arena = std:: mem:: take ( & mut self . arena )
742+ . into_iter ( )
743+ . filter_map ( |( id, data) | if to_keep. contains ( & id) { Some ( ( id, data) ) } else { None } )
744+ . enumerate ( )
745+ . map ( |( new_id, ( id, data) ) | {
746+ id_map[ id. into_raw ( ) . into_u32 ( ) as usize ] =
747+ Some ( CrateId :: from_raw ( RawIdx :: from_u32 ( new_id as u32 ) ) ) ;
748+ data
749+ } )
750+ . collect ( ) ;
751+ for ( _, data) in self . arena . iter_mut ( ) {
752+ data. dependencies . iter_mut ( ) . for_each ( |dep| {
753+ dep. crate_id =
754+ id_map[ dep. crate_id . into_raw ( ) . into_u32 ( ) as usize ] . expect ( "crate was filtered" )
755+ } ) ;
756+ }
757+ id_map
758+ }
724759}
725760
726761impl ops:: Index < CrateId > for CrateGraph {
0 commit comments