22//! metadata` or `rust-project.json`) into representation stored in the salsa
33//! database -- `CrateGraph`.
44
5+ use std:: thread:: Builder ;
56use std:: { collections:: VecDeque , fmt, fs, iter, ops:: Deref , sync, thread} ;
67
78use anyhow:: Context ;
@@ -12,7 +13,7 @@ use base_db::{
1213} ;
1314use cfg:: { CfgAtom , CfgDiff , CfgOptions } ;
1415use intern:: { Symbol , sym} ;
15- use paths:: { AbsPath , AbsPathBuf , Utf8PathBuf } ;
16+ use paths:: { AbsPath , AbsPathBuf , Utf8Path , Utf8PathBuf } ;
1617use rustc_hash:: { FxHashMap , FxHashSet } ;
1718use semver:: Version ;
1819use span:: { Edition , FileId } ;
@@ -301,31 +302,39 @@ impl ProjectWorkspace {
301302 // We can speed up loading a bit by spawning all of these processes in parallel (especially
302303 // on systems were process spawning is delayed)
303304 let join = thread:: scope ( |s| {
304- let rustc_cfg = s. spawn ( || {
305- rustc_cfg:: get ( toolchain_config, targets. first ( ) . map ( Deref :: deref) , extra_env)
306- } ) ;
307- let target_data = s. spawn ( || {
308- target_data:: get (
309- toolchain_config,
310- targets. first ( ) . map ( Deref :: deref) ,
311- extra_env,
312- ) . inspect_err ( |e| {
313- tracing:: error!( %e, "failed fetching data layout for {cargo_toml:?} workspace" )
305+ let rustc_cfg = Builder :: new ( )
306+ . name ( "ProjectWorkspace::rustc_cfg" . to_owned ( ) )
307+ . spawn_scoped ( s, || {
308+ rustc_cfg:: get ( toolchain_config, targets. first ( ) . map ( Deref :: deref) , extra_env)
314309 } )
315- } ) ;
316-
317- let rustc_dir = s. spawn ( || {
318- let rustc_dir = match rustc_source {
319- Some ( RustLibSource :: Path ( path) ) => ManifestPath :: try_from ( path. clone ( ) )
320- . map_err ( |p| Some ( format ! ( "rustc source path is not absolute: {p}" ) ) ) ,
321- Some ( RustLibSource :: Discover ) => {
322- sysroot. discover_rustc_src ( ) . ok_or_else ( || {
323- Some ( "Failed to discover rustc source for sysroot." . to_owned ( ) )
310+ . expect ( "failed to spawn thread" ) ;
311+ let target_data = Builder :: new ( )
312+ . name ( "ProjectWorkspace::target_data" . to_owned ( ) )
313+ . spawn_scoped ( s, || {
314+ target_data:: get ( toolchain_config, targets. first ( ) . map ( Deref :: deref) , extra_env)
315+ . inspect_err ( |e| {
316+ tracing:: error!( %e,
317+ "failed fetching data layout for \
318+ {cargo_toml:?} workspace"
319+ )
324320 } )
325- }
326- None => Err ( None ) ,
327- } ;
328- rustc_dir. and_then ( |rustc_dir| {
321+ } )
322+ . expect ( "failed to spawn thread" ) ;
323+
324+ let rustc_dir = Builder :: new ( )
325+ . name ( "ProjectWorkspace::rustc_dir" . to_owned ( ) )
326+ . spawn_scoped ( s, || {
327+ let rustc_dir = match rustc_source {
328+ Some ( RustLibSource :: Path ( path) ) => ManifestPath :: try_from ( path. clone ( ) )
329+ . map_err ( |p| Some ( format ! ( "rustc source path is not absolute: {p}" ) ) ) ,
330+ Some ( RustLibSource :: Discover ) => {
331+ sysroot. discover_rustc_src ( ) . ok_or_else ( || {
332+ Some ( "Failed to discover rustc source for sysroot." . to_owned ( ) )
333+ } )
334+ }
335+ None => Err ( None ) ,
336+ } ;
337+ rustc_dir. and_then ( |rustc_dir| {
329338 info ! ( workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source" ) ;
330339 match FetchMetadata :: new (
331340 & rustc_dir,
@@ -359,31 +368,44 @@ impl ProjectWorkspace {
359368 Err ( e) => {
360369 tracing:: error!(
361370 %e,
362- "Failed to read Cargo metadata from rustc source at {rustc_dir}" ,
371+ "Failed to read Cargo metadata from rustc source \
372+ at {rustc_dir}",
363373 ) ;
364374 Err ( Some ( format ! (
365- "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
375+ "Failed to read Cargo metadata from rustc source \
376+ at {rustc_dir}: {e}"
366377 ) ) )
367378 }
368379 }
369380 } )
370- } ) ;
371-
372- let cargo_metadata = s. spawn ( || fetch_metadata. exec ( false , progress) ) ;
373- let loaded_sysroot = s. spawn ( || {
374- sysroot. load_workspace (
375- & RustSourceWorkspaceConfig :: CargoMetadata ( sysroot_metadata_config (
376- config,
377- workspace_dir,
378- & targets,
379- toolchain. clone ( ) ,
380- ) ) ,
381- config. no_deps ,
382- progress,
383- )
384- } ) ;
385- let cargo_env =
386- s. spawn ( move || cargo_config_env ( cargo_toml, & config_file, & config. extra_env ) ) ;
381+ } )
382+ . expect ( "failed to spawn thread" ) ;
383+
384+ let cargo_metadata = Builder :: new ( )
385+ . name ( "ProjectWorkspace::cargo_metadata" . to_owned ( ) )
386+ . spawn_scoped ( s, || fetch_metadata. exec ( false , progress) )
387+ . expect ( "failed to spawn thread" ) ;
388+ let loaded_sysroot = Builder :: new ( )
389+ . name ( "ProjectWorkspace::loaded_sysroot" . to_owned ( ) )
390+ . spawn_scoped ( s, || {
391+ sysroot. load_workspace (
392+ & RustSourceWorkspaceConfig :: CargoMetadata ( sysroot_metadata_config (
393+ config,
394+ workspace_dir,
395+ & targets,
396+ toolchain. clone ( ) ,
397+ ) ) ,
398+ config. no_deps ,
399+ progress,
400+ )
401+ } )
402+ . expect ( "failed to spawn thread" ) ;
403+ let cargo_env = Builder :: new ( )
404+ . name ( "ProjectWorkspace::cargo_env" . to_owned ( ) )
405+ . spawn_scoped ( s, move || {
406+ cargo_config_env ( cargo_toml, & config_file, & config. extra_env )
407+ } )
408+ . expect ( "failed to spawn thread" ) ;
387409 thread:: Result :: Ok ( (
388410 rustc_cfg. join ( ) ?,
389411 target_data. join ( ) ?,
@@ -1194,6 +1216,7 @@ fn cargo_to_crate_graph(
11941216 load,
11951217 crate_ws_data. clone ( ) ,
11961218 ) ;
1219+ let cargo_path = sysroot. tool_path ( Tool :: Cargo , cargo. workspace_root ( ) , cargo. env ( ) ) ;
11971220
11981221 let cfg_options = CfgOptions :: from_iter ( rustc_cfg) ;
11991222
@@ -1268,6 +1291,7 @@ fn cargo_to_crate_graph(
12681291 } else {
12691292 Arc :: new ( pkg_data. manifest . parent ( ) . to_path_buf ( ) )
12701293 } ,
1294+ & cargo_path,
12711295 ) ;
12721296 if let TargetKind :: Lib { .. } = kind {
12731297 lib_tgt = Some ( ( crate_id, name. clone ( ) ) ) ;
@@ -1375,6 +1399,7 @@ fn cargo_to_crate_graph(
13751399 } ,
13761400 // FIXME: This looks incorrect but I don't think this causes problems.
13771401 crate_ws_data,
1402+ & cargo_path,
13781403 ) ;
13791404 }
13801405 }
@@ -1453,6 +1478,7 @@ fn handle_rustc_crates(
14531478 override_cfg : & CfgOverrides ,
14541479 build_scripts : & WorkspaceBuildScripts ,
14551480 crate_ws_data : Arc < CrateWorkspaceData > ,
1481+ cargo_path : & Utf8Path ,
14561482) {
14571483 let mut rustc_pkg_crates = FxHashMap :: default ( ) ;
14581484 // The root package of the rustc-dev component is rustc_driver, so we match that
@@ -1503,6 +1529,7 @@ fn handle_rustc_crates(
15031529 } else {
15041530 Arc :: new ( pkg_data. manifest . parent ( ) . to_path_buf ( ) )
15051531 } ,
1532+ cargo_path,
15061533 ) ;
15071534 pkg_to_lib_crate. insert ( pkg, crate_id) ;
15081535 // Add dependencies on core / std / alloc for this crate
@@ -1560,11 +1587,12 @@ fn add_target_crate_root(
15601587 build_data : Option < ( & BuildScriptOutput , bool ) > ,
15611588 cfg_options : CfgOptions ,
15621589 file_id : FileId ,
1563- cargo_name : & str ,
1590+ cargo_crate_name : & str ,
15641591 kind : TargetKind ,
15651592 origin : CrateOrigin ,
15661593 crate_ws_data : Arc < CrateWorkspaceData > ,
15671594 proc_macro_cwd : Arc < AbsPathBuf > ,
1595+ cargo_path : & Utf8Path ,
15681596) -> CrateBuilderId {
15691597 let edition = pkg. edition ;
15701598 let potential_cfg_options = if pkg. features . is_empty ( ) {
@@ -1591,16 +1619,16 @@ fn add_target_crate_root(
15911619
15921620 let mut env = cargo. env ( ) . clone ( ) ;
15931621 inject_cargo_package_env ( & mut env, pkg) ;
1594- inject_cargo_env ( & mut env) ;
1595- inject_rustc_tool_env ( & mut env, cargo_name , kind) ;
1622+ inject_cargo_env ( & mut env, cargo_path ) ;
1623+ inject_rustc_tool_env ( & mut env, cargo_crate_name , kind) ;
15961624
15971625 if let Some ( envs) = build_data. map ( |( it, _) | & it. envs ) {
15981626 env. extend_from_other ( envs) ;
15991627 }
16001628 let crate_id = crate_graph. add_crate_root (
16011629 file_id,
16021630 edition,
1603- Some ( CrateDisplayName :: from_canonical_name ( cargo_name ) ) ,
1631+ Some ( CrateDisplayName :: from_canonical_name ( cargo_crate_name ) ) ,
16041632 Some ( pkg. version . to_string ( ) ) ,
16051633 cfg_options,
16061634 potential_cfg_options,
@@ -1614,7 +1642,9 @@ fn add_target_crate_root(
16141642 let proc_macro = match build_data {
16151643 Some ( ( BuildScriptOutput { proc_macro_dylib_path, .. } , has_errors) ) => {
16161644 match proc_macro_dylib_path {
1617- ProcMacroDylibPath :: Path ( path) => Ok ( ( cargo_name. to_owned ( ) , path. clone ( ) ) ) ,
1645+ ProcMacroDylibPath :: Path ( path) => {
1646+ Ok ( ( cargo_crate_name. to_owned ( ) , path. clone ( ) ) )
1647+ }
16181648 ProcMacroDylibPath :: NotBuilt => Err ( ProcMacroLoadingError :: NotYetBuilt ) ,
16191649 ProcMacroDylibPath :: NotProcMacro | ProcMacroDylibPath :: DylibNotFound
16201650 if has_errors =>
0 commit comments