@@ -30,6 +30,7 @@ pub struct Sysroot {
3030pub enum RustLibSrcWorkspace {
3131 Workspace ( CargoWorkspace ) ,
3232 Json ( ProjectJson ) ,
33+ Stitched ( stitched:: Stitched ) ,
3334 Empty ,
3435}
3536
@@ -60,6 +61,7 @@ impl Sysroot {
6061 match & self . workspace {
6162 RustLibSrcWorkspace :: Workspace ( ws) => ws. packages ( ) . next ( ) . is_none ( ) ,
6263 RustLibSrcWorkspace :: Json ( project_json) => project_json. n_crates ( ) == 0 ,
64+ RustLibSrcWorkspace :: Stitched ( stitched) => stitched. crates . is_empty ( ) ,
6365 RustLibSrcWorkspace :: Empty => true ,
6466 }
6567 }
@@ -72,6 +74,7 @@ impl Sysroot {
7274 match & self . workspace {
7375 RustLibSrcWorkspace :: Workspace ( ws) => ws. packages ( ) . count ( ) ,
7476 RustLibSrcWorkspace :: Json ( project_json) => project_json. n_crates ( ) ,
77+ RustLibSrcWorkspace :: Stitched ( stitched) => stitched. crates . len ( ) ,
7578 RustLibSrcWorkspace :: Empty => 0 ,
7679 }
7780 }
@@ -197,6 +200,51 @@ impl Sysroot {
197200 return Some ( loaded) ;
198201 }
199202 }
203+ tracing:: debug!( "Stitching sysroot library: {src_root}" ) ;
204+
205+ let mut stitched = stitched:: Stitched { crates : Default :: default ( ) } ;
206+
207+ for path in stitched:: SYSROOT_CRATES . trim ( ) . lines ( ) {
208+ let name = path. split ( '/' ) . next_back ( ) . unwrap ( ) ;
209+ let root = [ format ! ( "{path}/src/lib.rs" ) , format ! ( "lib{path}/lib.rs" ) ]
210+ . into_iter ( )
211+ . map ( |it| src_root. join ( it) )
212+ . filter_map ( |it| ManifestPath :: try_from ( it) . ok ( ) )
213+ . find ( |it| fs:: metadata ( it) . is_ok ( ) ) ;
214+
215+ if let Some ( root) = root {
216+ stitched. crates . alloc ( stitched:: RustLibSrcCrateData {
217+ name : name. into ( ) ,
218+ root,
219+ deps : Vec :: new ( ) ,
220+ } ) ;
221+ }
222+ }
223+
224+ if let Some ( std) = stitched. by_name ( "std" ) {
225+ for dep in stitched:: STD_DEPS . trim ( ) . lines ( ) {
226+ if let Some ( dep) = stitched. by_name ( dep) {
227+ stitched. crates [ std] . deps . push ( dep)
228+ }
229+ }
230+ }
231+
232+ if let Some ( alloc) = stitched. by_name ( "alloc" ) {
233+ for dep in stitched:: ALLOC_DEPS . trim ( ) . lines ( ) {
234+ if let Some ( dep) = stitched. by_name ( dep) {
235+ stitched. crates [ alloc] . deps . push ( dep)
236+ }
237+ }
238+ }
239+
240+ if let Some ( proc_macro) = stitched. by_name ( "proc_macro" ) {
241+ for dep in stitched:: PROC_MACRO_DEPS . trim ( ) . lines ( ) {
242+ if let Some ( dep) = stitched. by_name ( dep) {
243+ stitched. crates [ proc_macro] . deps . push ( dep)
244+ }
245+ }
246+ }
247+ return Some ( RustLibSrcWorkspace :: Stitched ( stitched) ) ;
200248 } else if let RustSourceWorkspaceConfig :: Json ( project_json) = sysroot_source_config {
201249 return Some ( RustLibSrcWorkspace :: Json ( project_json. clone ( ) ) ) ;
202250 }
@@ -216,6 +264,7 @@ impl Sysroot {
216264 . crates ( )
217265 . filter_map ( |( _, krate) | krate. display_name . clone ( ) )
218266 . any ( |name| name. canonical_name ( ) . as_str ( ) == "core" ) ,
267+ RustLibSrcWorkspace :: Stitched ( stitched) => stitched. by_name ( "core" ) . is_some ( ) ,
219268 RustLibSrcWorkspace :: Empty => true ,
220269 } ;
221270 if !has_core {
@@ -391,3 +440,91 @@ fn get_rust_lib_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
391440 None
392441 }
393442}
443+
444+ // FIXME: Remove this, that will bump our project MSRV to 1.82
445+ pub ( crate ) mod stitched {
446+ use std:: ops;
447+
448+ use base_db:: CrateName ;
449+ use la_arena:: { Arena , Idx } ;
450+
451+ use crate :: ManifestPath ;
452+
453+ #[ derive( Debug , Clone , Eq , PartialEq ) ]
454+ pub struct Stitched {
455+ pub ( super ) crates : Arena < RustLibSrcCrateData > ,
456+ }
457+
458+ impl ops:: Index < RustLibSrcCrate > for Stitched {
459+ type Output = RustLibSrcCrateData ;
460+ fn index ( & self , index : RustLibSrcCrate ) -> & RustLibSrcCrateData {
461+ & self . crates [ index]
462+ }
463+ }
464+
465+ impl Stitched {
466+ pub ( crate ) fn public_deps (
467+ & self ,
468+ ) -> impl Iterator < Item = ( CrateName , RustLibSrcCrate , bool ) > + ' _ {
469+ // core is added as a dependency before std in order to
470+ // mimic rustcs dependency order
471+ [ ( "core" , true ) , ( "alloc" , false ) , ( "std" , true ) , ( "test" , false ) ]
472+ . into_iter ( )
473+ . filter_map ( move |( name, prelude) | {
474+ Some ( ( CrateName :: new ( name) . unwrap ( ) , self . by_name ( name) ?, prelude) )
475+ } )
476+ }
477+
478+ pub ( crate ) fn proc_macro ( & self ) -> Option < RustLibSrcCrate > {
479+ self . by_name ( "proc_macro" )
480+ }
481+
482+ pub ( crate ) fn crates ( & self ) -> impl ExactSizeIterator < Item = RustLibSrcCrate > + ' _ {
483+ self . crates . iter ( ) . map ( |( id, _data) | id)
484+ }
485+
486+ pub ( super ) fn by_name ( & self , name : & str ) -> Option < RustLibSrcCrate > {
487+ let ( id, _data) = self . crates . iter ( ) . find ( |( _id, data) | data. name == name) ?;
488+ Some ( id)
489+ }
490+ }
491+
492+ pub ( crate ) type RustLibSrcCrate = Idx < RustLibSrcCrateData > ;
493+
494+ #[ derive( Debug , Clone , Eq , PartialEq ) ]
495+ pub ( crate ) struct RustLibSrcCrateData {
496+ pub ( crate ) name : String ,
497+ pub ( crate ) root : ManifestPath ,
498+ pub ( crate ) deps : Vec < RustLibSrcCrate > ,
499+ }
500+
501+ pub ( super ) const SYSROOT_CRATES : & str = "
502+ alloc
503+ backtrace
504+ core
505+ panic_abort
506+ panic_unwind
507+ proc_macro
508+ profiler_builtins
509+ std
510+ stdarch/crates/std_detect
511+ test
512+ unwind" ;
513+
514+ pub ( super ) const ALLOC_DEPS : & str = "core" ;
515+
516+ pub ( super ) const STD_DEPS : & str = "
517+ alloc
518+ panic_unwind
519+ panic_abort
520+ core
521+ profiler_builtins
522+ unwind
523+ std_detect
524+ test" ;
525+
526+ // core is required for our builtin derives to work in the proc_macro lib currently
527+ pub ( super ) const PROC_MACRO_DEPS : & str = "
528+ std
529+ core" ;
530+ }
0 commit comments