@@ -30,6 +30,7 @@ pub struct Sysroot {
30
30
pub enum RustLibSrcWorkspace {
31
31
Workspace ( CargoWorkspace ) ,
32
32
Json ( ProjectJson ) ,
33
+ Stitched ( stitched:: Stitched ) ,
33
34
Empty ,
34
35
}
35
36
@@ -60,6 +61,7 @@ impl Sysroot {
60
61
match & self . workspace {
61
62
RustLibSrcWorkspace :: Workspace ( ws) => ws. packages ( ) . next ( ) . is_none ( ) ,
62
63
RustLibSrcWorkspace :: Json ( project_json) => project_json. n_crates ( ) == 0 ,
64
+ RustLibSrcWorkspace :: Stitched ( stitched) => stitched. crates . is_empty ( ) ,
63
65
RustLibSrcWorkspace :: Empty => true ,
64
66
}
65
67
}
@@ -72,6 +74,7 @@ impl Sysroot {
72
74
match & self . workspace {
73
75
RustLibSrcWorkspace :: Workspace ( ws) => ws. packages ( ) . count ( ) ,
74
76
RustLibSrcWorkspace :: Json ( project_json) => project_json. n_crates ( ) ,
77
+ RustLibSrcWorkspace :: Stitched ( stitched) => stitched. crates . len ( ) ,
75
78
RustLibSrcWorkspace :: Empty => 0 ,
76
79
}
77
80
}
@@ -197,6 +200,51 @@ impl Sysroot {
197
200
return Some ( loaded) ;
198
201
}
199
202
}
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) ) ;
200
248
} else if let RustSourceWorkspaceConfig :: Json ( project_json) = sysroot_source_config {
201
249
return Some ( RustLibSrcWorkspace :: Json ( project_json. clone ( ) ) ) ;
202
250
}
@@ -216,6 +264,7 @@ impl Sysroot {
216
264
. crates ( )
217
265
. filter_map ( |( _, krate) | krate. display_name . clone ( ) )
218
266
. any ( |name| name. canonical_name ( ) . as_str ( ) == "core" ) ,
267
+ RustLibSrcWorkspace :: Stitched ( stitched) => stitched. by_name ( "core" ) . is_some ( ) ,
219
268
RustLibSrcWorkspace :: Empty => true ,
220
269
} ;
221
270
if !has_core {
@@ -391,3 +440,91 @@ fn get_rust_lib_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
391
440
None
392
441
}
393
442
}
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