Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/project-model/src/workspace.rs')
-rw-r--r--crates/project-model/src/workspace.rs172
1 files changed, 113 insertions, 59 deletions
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 16b5bb11af..7b964d201b 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -69,6 +69,7 @@ pub struct ProjectWorkspace {
}
#[derive(Clone)]
+#[allow(clippy::large_enum_variant)]
pub enum ProjectWorkspaceKind {
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
Cargo {
@@ -400,20 +401,17 @@ impl ProjectWorkspace {
}
pub fn load_inline(
- project_json: ProjectJson,
+ mut project_json: ProjectJson,
config: &CargoConfig,
progress: &dyn Fn(String),
) -> ProjectWorkspace {
progress("Discovering sysroot".to_owned());
let mut sysroot =
Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone());
- let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::Stitched);
- if let Some(loaded_sysroot) = loaded_sysroot {
- sysroot.set_workspace(loaded_sysroot);
- }
tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
progress("Querying project metadata".to_owned());
+ let sysroot_project = project_json.sysroot_project.take();
let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref());
let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
.unwrap_or_default();
@@ -435,14 +433,31 @@ impl ProjectWorkspace {
&config.extra_env,
)
});
- thread::Result::Ok((toolchain.join()?, rustc_cfg.join()?, data_layout.join()?))
+ let loaded_sysroot = s.spawn(|| {
+ if let Some(sysroot_project) = sysroot_project {
+ sysroot.load_workspace(&RustSourceWorkspaceConfig::Json(*sysroot_project))
+ } else {
+ sysroot.load_workspace(&RustSourceWorkspaceConfig::Stitched)
+ }
+ });
+
+ thread::Result::Ok((
+ toolchain.join()?,
+ rustc_cfg.join()?,
+ data_layout.join()?,
+ loaded_sysroot.join()?,
+ ))
});
- let (toolchain, rustc_cfg, target_layout) = match join {
+ let (toolchain, rustc_cfg, target_layout, loaded_sysroot) = match join {
Ok(it) => it,
Err(e) => std::panic::resume_unwind(e),
};
+ if let Some(loaded_sysroot) = loaded_sysroot {
+ sysroot.set_workspace(loaded_sysroot);
+ }
+
ProjectWorkspace {
kind: ProjectWorkspaceKind::Json(project_json),
sysroot,
@@ -667,6 +682,14 @@ impl ProjectWorkspace {
Some(PackageRoot { is_local: false, include, exclude })
})
.collect(),
+ RustLibSrcWorkspace::Json(project_json) => project_json
+ .crates()
+ .map(|(_, krate)| PackageRoot {
+ is_local: false,
+ include: krate.include.clone(),
+ exclude: krate.exclude.clone(),
+ })
+ .collect(),
RustLibSrcWorkspace::Stitched(_) | RustLibSrcWorkspace::Empty => vec![],
};
@@ -1490,6 +1513,65 @@ impl SysrootPublicDeps {
}
}
+fn extend_crate_graph_with_sysroot(
+ crate_graph: &mut CrateGraph,
+ mut sysroot_crate_graph: CrateGraph,
+ mut sysroot_proc_macros: ProcMacroPaths,
+) -> (SysrootPublicDeps, Option<CrateId>) {
+ let mut pub_deps = vec![];
+ let mut libproc_macro = None;
+ let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap();
+ for (cid, c) in sysroot_crate_graph.iter_mut() {
+ // uninject `test` flag so `core` keeps working.
+ Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
+ // patch the origin
+ if c.origin.is_local() {
+ let lang_crate = LangCrateOrigin::from(
+ c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
+ );
+ c.origin = CrateOrigin::Lang(lang_crate);
+ match lang_crate {
+ LangCrateOrigin::Test
+ | LangCrateOrigin::Alloc
+ | LangCrateOrigin::Core
+ | LangCrateOrigin::Std => pub_deps.push((
+ CrateName::normalize_dashes(&lang_crate.to_string()),
+ cid,
+ !matches!(lang_crate, LangCrateOrigin::Test | LangCrateOrigin::Alloc),
+ )),
+ LangCrateOrigin::ProcMacro => libproc_macro = Some(cid),
+ LangCrateOrigin::Other => (),
+ }
+ }
+ }
+
+ let mut marker_set = vec![];
+ for &(_, cid, _) in pub_deps.iter() {
+ marker_set.extend(sysroot_crate_graph.transitive_deps(cid));
+ }
+ if let Some(cid) = libproc_macro {
+ marker_set.extend(sysroot_crate_graph.transitive_deps(cid));
+ }
+
+ marker_set.sort();
+ marker_set.dedup();
+
+ // Remove all crates except the ones we are interested in to keep the sysroot graph small.
+ let removed_mapping = sysroot_crate_graph.remove_crates_except(&marker_set);
+ let mapping = crate_graph.extend(sysroot_crate_graph, &mut sysroot_proc_macros);
+
+ // Map the id through the removal mapping first, then through the crate graph extension mapping.
+ pub_deps.iter_mut().for_each(|(_, cid, _)| {
+ *cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
+ });
+ if let Some(libproc_macro) = &mut libproc_macro {
+ *libproc_macro =
+ mapping[&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
+ }
+
+ (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
+}
+
fn sysroot_to_crate_graph(
crate_graph: &mut CrateGraph,
sysroot: &Sysroot,
@@ -1499,7 +1581,7 @@ fn sysroot_to_crate_graph(
let _p = tracing::info_span!("sysroot_to_crate_graph").entered();
match sysroot.workspace() {
RustLibSrcWorkspace::Workspace(cargo) => {
- let (mut cg, mut pm) = cargo_to_crate_graph(
+ let (cg, pm) = cargo_to_crate_graph(
load,
None,
cargo,
@@ -1520,58 +1602,30 @@ fn sysroot_to_crate_graph(
false,
);
- let mut pub_deps = vec![];
- let mut libproc_macro = None;
- let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap();
- for (cid, c) in cg.iter_mut() {
- // uninject `test` flag so `core` keeps working.
- Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
- // patch the origin
- if c.origin.is_local() {
- let lang_crate = LangCrateOrigin::from(
- c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
- );
- c.origin = CrateOrigin::Lang(lang_crate);
- match lang_crate {
- LangCrateOrigin::Test
- | LangCrateOrigin::Alloc
- | LangCrateOrigin::Core
- | LangCrateOrigin::Std => pub_deps.push((
- CrateName::normalize_dashes(&lang_crate.to_string()),
- cid,
- !matches!(lang_crate, LangCrateOrigin::Test | LangCrateOrigin::Alloc),
- )),
- LangCrateOrigin::ProcMacro => libproc_macro = Some(cid),
- LangCrateOrigin::Other => (),
- }
- }
- }
-
- let mut marker_set = vec![];
- for &(_, cid, _) in pub_deps.iter() {
- marker_set.extend(cg.transitive_deps(cid));
- }
- if let Some(cid) = libproc_macro {
- marker_set.extend(cg.transitive_deps(cid));
- }
-
- marker_set.sort();
- marker_set.dedup();
-
- // Remove all crates except the ones we are interested in to keep the sysroot graph small.
- let removed_mapping = cg.remove_crates_except(&marker_set);
- let mapping = crate_graph.extend(cg, &mut pm);
-
- // Map the id through the removal mapping first, then through the crate graph extension mapping.
- pub_deps.iter_mut().for_each(|(_, cid, _)| {
- *cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
- });
- if let Some(libproc_macro) = &mut libproc_macro {
- *libproc_macro = mapping
- [&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
- }
+ extend_crate_graph_with_sysroot(crate_graph, cg, pm)
+ }
+ RustLibSrcWorkspace::Json(project_json) => {
+ let (cg, pm) = project_json_to_crate_graph(
+ rustc_cfg,
+ load,
+ project_json,
+ &Sysroot::empty(),
+ &FxHashMap::default(),
+ &CfgOverrides {
+ global: CfgDiff::new(
+ vec![
+ CfgAtom::Flag(sym::debug_assertions.clone()),
+ CfgAtom::Flag(sym::miri.clone()),
+ ],
+ vec![],
+ )
+ .unwrap(),
+ ..Default::default()
+ },
+ false,
+ );
- (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
+ extend_crate_graph_with_sysroot(crate_graph, cg, pm)
}
RustLibSrcWorkspace::Stitched(stitched) => {
let cfg_options = Arc::new({