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.rs535
1 files changed, 218 insertions, 317 deletions
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 98c5a02dcd..85621444e3 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -4,7 +4,7 @@
use std::{collections::VecDeque, fmt, fs, iter, sync};
-use anyhow::{format_err, Context};
+use anyhow::Context;
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileId,
LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
@@ -14,8 +14,8 @@ use paths::{AbsPath, AbsPathBuf};
use rustc_hash::{FxHashMap, FxHashSet};
use semver::Version;
use span::Edition;
-use stdx::always;
use toolchain::Tool;
+use tracing::instrument;
use triomphe::Arc;
use crate::{
@@ -45,50 +45,39 @@ pub struct PackageRoot {
}
#[derive(Clone)]
-pub enum ProjectWorkspace {
+pub struct ProjectWorkspace {
+ pub kind: ProjectWorkspaceKind,
+ /// The sysroot loaded for this workspace.
+ pub sysroot: Result<Sysroot, Option<String>>,
+ /// Holds cfg flags for the current target. We get those by running
+ /// `rustc --print cfg`.
+ // FIXME: make this a per-crate map, as, eg, build.rs might have a
+ // different target.
+ pub rustc_cfg: Vec<CfgFlag>,
+ /// The toolchain version used by this workspace.
+ pub toolchain: Option<Version>,
+ /// The target data layout queried for workspace.
+ pub target_layout: TargetLayoutLoadResult,
+ /// A set of cfg overrides for this workspace.
+ pub cfg_overrides: CfgOverrides,
+}
+
+#[derive(Clone)]
+pub enum ProjectWorkspaceKind {
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
Cargo {
/// The workspace as returned by `cargo metadata`.
cargo: CargoWorkspace,
/// The build script results for the workspace.
build_scripts: WorkspaceBuildScripts,
- /// The sysroot loaded for this workspace.
- sysroot: Result<Sysroot, Option<String>>,
/// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been
/// disabled or was otherwise not requested.
rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>,
- /// Holds cfg flags for the current target. We get those by running
- /// `rustc --print cfg`.
- // FIXME: make this a per-crate map, as, eg, build.rs might have a
- // different target.
- rustc_cfg: Vec<CfgFlag>,
- /// A set of cfg overrides for this workspace.
- cfg_overrides: CfgOverrides,
- /// The toolchain version used by this workspace.
- toolchain: Option<Version>,
- /// The target data layout queried for workspace.
- target_layout: TargetLayoutLoadResult,
/// Environment variables set in the `.cargo/config` file.
cargo_config_extra_env: FxHashMap<String, String>,
},
/// Project workspace was manually specified using a `rust-project.json` file.
- Json {
- /// The loaded project json file.
- project: ProjectJson,
- /// The sysroot loaded for this workspace.
- sysroot: Result<Sysroot, Option<String>>,
- /// Holds cfg flags for the current target. We get those by running
- /// `rustc --print cfg`.
- // FIXME: make this a per-crate map, as, eg, build.rs might have a
- // different target.
- rustc_cfg: Vec<CfgFlag>,
- /// The toolchain version used by this workspace.
- toolchain: Option<Version>,
- /// The target data layout queried for workspace.
- target_layout: TargetLayoutLoadResult,
- /// A set of cfg overrides for this workspace.
- cfg_overrides: CfgOverrides,
- },
+ Json(ProjectJson),
// FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning.
// That's not the end user experience we should strive for.
// Ideally, you should be able to just open a random detached file in existing cargo projects, and get the basic features working.
@@ -101,38 +90,23 @@ pub enum ProjectWorkspace {
/// Backed by basic sysroot crates for basic completion and highlighting.
DetachedFile {
/// The file in question.
- file: AbsPathBuf,
- /// The sysroot loaded for this workspace.
- sysroot: Result<Sysroot, Option<String>>,
- /// Holds cfg flags for the current target. We get those by running
- /// `rustc --print cfg`.
- // FIXME: make this a per-crate map, as, eg, build.rs might have a
- // different target.
- rustc_cfg: Vec<CfgFlag>,
- /// The toolchain version used by this workspace.
- toolchain: Option<Version>,
- /// The target data layout queried for workspace.
- target_layout: TargetLayoutLoadResult,
- /// A set of cfg overrides for the files.
- cfg_overrides: CfgOverrides,
+ file: ManifestPath,
/// Is this file a cargo script file?
- cargo_script: Option<CargoWorkspace>,
+ cargo: Option<(CargoWorkspace, WorkspaceBuildScripts)>,
+ /// Environment variables set in the `.cargo/config` file.
+ cargo_config_extra_env: FxHashMap<String, String>,
},
}
impl fmt::Debug for ProjectWorkspace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Make sure this isn't too verbose.
- match self {
- ProjectWorkspace::Cargo {
+ let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides } = self;
+ match kind {
+ ProjectWorkspaceKind::Cargo {
cargo,
build_scripts: _,
- sysroot,
rustc,
- rustc_cfg,
- cfg_overrides,
- toolchain,
- target_layout,
cargo_config_extra_env,
} => f
.debug_struct("Cargo")
@@ -149,14 +123,7 @@ impl fmt::Debug for ProjectWorkspace {
.field("data_layout", &target_layout)
.field("cargo_config_extra_env", &cargo_config_extra_env)
.finish(),
- ProjectWorkspace::Json {
- project,
- sysroot,
- rustc_cfg,
- toolchain,
- target_layout: data_layout,
- cfg_overrides,
- } => {
+ ProjectWorkspaceKind::Json(project) => {
let mut debug_struct = f.debug_struct("Json");
debug_struct.field("n_crates", &project.n_crates());
if let Ok(sysroot) = sysroot {
@@ -165,18 +132,14 @@ impl fmt::Debug for ProjectWorkspace {
debug_struct
.field("n_rustc_cfg", &rustc_cfg.len())
.field("toolchain", &toolchain)
- .field("data_layout", &data_layout)
+ .field("data_layout", &target_layout)
.field("n_cfg_overrides", &cfg_overrides.len());
debug_struct.finish()
}
- ProjectWorkspace::DetachedFile {
+ ProjectWorkspaceKind::DetachedFile {
file,
- sysroot,
- rustc_cfg,
- toolchain,
- target_layout,
- cfg_overrides,
- cargo_script,
+ cargo: cargo_script,
+ cargo_config_extra_env,
} => f
.debug_struct("DetachedFiles")
.field("file", &file)
@@ -187,6 +150,7 @@ impl fmt::Debug for ProjectWorkspace {
.field("toolchain", &toolchain)
.field("data_layout", &target_layout)
.field("n_cfg_overrides", &cfg_overrides.len())
+ .field("cargo_config_extra_env", &cargo_config_extra_env)
.finish(),
}
}
@@ -230,12 +194,13 @@ impl ProjectWorkspace {
) -> anyhow::Result<ProjectWorkspace> {
let res = match manifest {
ProjectManifest::ProjectJson(project_json) => {
- let file = fs::read_to_string(project_json)
+ let file = fs::read_to_string(project_json.as_ref())
.with_context(|| format!("Failed to read json file {project_json}"))?;
let data = serde_json::from_str(&file)
.with_context(|| format!("Failed to deserialize json file {project_json}"))?;
let project_location = project_json.parent().to_path_buf();
- let project_json: ProjectJson = ProjectJson::new(&project_location, data);
+ let project_json: ProjectJson =
+ ProjectJson::new(Some(project_json.clone()), &project_location, data);
ProjectWorkspace::load_inline(
project_json,
config.target.as_deref(),
@@ -243,6 +208,9 @@ impl ProjectWorkspace {
&config.cfg_overrides,
)
}
+ ProjectManifest::CargoScript(rust_file) => {
+ ProjectWorkspace::load_detached_file(rust_file, config)?
+ }
ProjectManifest::CargoToml(cargo_toml) => {
let sysroot = match (&config.sysroot, &config.sysroot_src) {
(Some(RustLibSource::Path(path)), None) => {
@@ -299,7 +267,7 @@ impl ProjectWorkspace {
progress,
) {
Ok(meta) => {
- let workspace = CargoWorkspace::new(meta);
+ let workspace = CargoWorkspace::new(meta, cargo_toml.clone());
let buildscripts = WorkspaceBuildScripts::rustc_crates(
&workspace,
cargo_toml.parent(),
@@ -355,22 +323,24 @@ impl ProjectWorkspace {
"Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
)
})?;
- let cargo = CargoWorkspace::new(meta);
+ let cargo = CargoWorkspace::new(meta, cargo_toml.clone());
let cargo_config_extra_env =
cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref);
- ProjectWorkspace::Cargo {
- cargo,
- build_scripts: WorkspaceBuildScripts::default(),
+ ProjectWorkspace {
+ kind: ProjectWorkspaceKind::Cargo {
+ cargo,
+ build_scripts: WorkspaceBuildScripts::default(),
+ rustc,
+ cargo_config_extra_env,
+ },
sysroot,
- rustc,
rustc_cfg,
cfg_overrides,
toolchain,
target_layout: data_layout
.map(Arc::from)
.map_err(|it| Arc::from(it.to_string())),
- cargo_config_extra_env,
}
}
};
@@ -423,8 +393,8 @@ impl ProjectWorkspace {
let rustc_cfg = rustc_cfg::get(target, extra_env, cfg_config);
let data_layout = target_data_layout::get(data_layout_config, target, extra_env);
- ProjectWorkspace::Json {
- project: project_json,
+ ProjectWorkspace {
+ kind: ProjectWorkspaceKind::Json(project_json),
sysroot,
rustc_cfg,
toolchain,
@@ -433,82 +403,76 @@ impl ProjectWorkspace {
}
}
- pub fn load_detached_files(
- detached_files: Vec<AbsPathBuf>,
+ pub fn load_detached_file(
+ detached_file: &ManifestPath,
config: &CargoConfig,
- ) -> Vec<anyhow::Result<ProjectWorkspace>> {
- detached_files
- .into_iter()
- .map(|detached_file| {
- let dir = detached_file
- .parent()
- .ok_or_else(|| format_err!("detached file has no parent"))?;
- let sysroot = match &config.sysroot {
- Some(RustLibSource::Path(path)) => {
- Sysroot::with_sysroot_dir(path.clone(), config.sysroot_query_metadata)
- .map_err(|e| Some(format!("Failed to find sysroot at {path}:{e}")))
- }
- Some(RustLibSource::Discover) => {
- Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
- .map_err(|e| {
- Some(format!(
- "Failed to find sysroot for {dir}. Is rust-src installed? {e}"
- ))
- })
- }
- None => Err(None),
- };
+ ) -> anyhow::Result<ProjectWorkspace> {
+ let dir = detached_file.parent();
+ let sysroot = match &config.sysroot {
+ Some(RustLibSource::Path(path)) => {
+ Sysroot::with_sysroot_dir(path.clone(), config.sysroot_query_metadata)
+ .map_err(|e| Some(format!("Failed to find sysroot at {path}:{e}")))
+ }
+ Some(RustLibSource::Discover) => Sysroot::discover(
+ dir,
+ &config.extra_env,
+ config.sysroot_query_metadata,
+ )
+ .map_err(|e| {
+ Some(format!("Failed to find sysroot for {dir}. Is rust-src installed? {e}"))
+ }),
+ None => Err(None),
+ };
- let sysroot_ref = sysroot.as_ref().ok();
- let toolchain = match get_toolchain_version(
- dir,
- sysroot_ref,
- Tool::Rustc,
- &config.extra_env,
- "rustc ",
- ) {
- Ok(it) => it,
- Err(e) => {
- tracing::error!("{e}");
- None
- }
- };
+ let sysroot_ref = sysroot.as_ref().ok();
+ let toolchain =
+ match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ")
+ {
+ Ok(it) => it,
+ Err(e) => {
+ tracing::error!("{e}");
+ None
+ }
+ };
- let rustc_cfg =
- rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
- let data_layout = target_data_layout::get(
- RustcDataLayoutConfig::Rustc(sysroot_ref),
- None,
- &config.extra_env,
- );
+ let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
+ let data_layout = target_data_layout::get(
+ RustcDataLayoutConfig::Rustc(sysroot_ref),
+ None,
+ &config.extra_env,
+ );
- let cargo_script = ManifestPath::try_from(detached_file.clone())
- .ok()
- .and_then(|file| {
- CargoWorkspace::fetch_metadata(
- &file,
- file.parent(),
- config,
- sysroot_ref,
- &|_| (),
- )
- .ok()
- })
- .map(CargoWorkspace::new);
+ let cargo_script =
+ CargoWorkspace::fetch_metadata(detached_file, dir, config, sysroot_ref, &|_| ())
+ .ok()
+ .map(|ws| {
+ (
+ CargoWorkspace::new(ws, detached_file.clone()),
+ WorkspaceBuildScripts::default(),
+ )
+ });
- Ok(ProjectWorkspace::DetachedFile {
- file: detached_file,
- sysroot,
- rustc_cfg,
- toolchain,
- target_layout: data_layout
- .map(Arc::from)
- .map_err(|it| Arc::from(it.to_string())),
- cfg_overrides: config.cfg_overrides.clone(),
- cargo_script,
- })
- })
- .collect()
+ let cargo_config_extra_env =
+ cargo_config_env(detached_file, &config.extra_env, sysroot_ref);
+ Ok(ProjectWorkspace {
+ kind: ProjectWorkspaceKind::DetachedFile {
+ file: detached_file.to_owned(),
+ cargo: cargo_script,
+ cargo_config_extra_env,
+ },
+ sysroot,
+ rustc_cfg,
+ toolchain,
+ target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+ cfg_overrides: config.cfg_overrides.clone(),
+ })
+ }
+
+ pub fn load_detached_files(
+ detached_files: Vec<ManifestPath>,
+ config: &CargoConfig,
+ ) -> Vec<anyhow::Result<ProjectWorkspace>> {
+ detached_files.into_iter().map(|file| Self::load_detached_file(&file, config)).collect()
}
/// Runs the build scripts for this [`ProjectWorkspace`].
@@ -517,27 +481,22 @@ impl ProjectWorkspace {
config: &CargoConfig,
progress: &dyn Fn(String),
) -> anyhow::Result<WorkspaceBuildScripts> {
- match self {
- ProjectWorkspace::DetachedFile {
- cargo_script: Some(cargo),
- toolchain,
- sysroot,
- ..
- }
- | ProjectWorkspace::Cargo { cargo, toolchain, sysroot, .. } => {
+ match &self.kind {
+ ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. }
+ | ProjectWorkspaceKind::Cargo { cargo, .. } => {
WorkspaceBuildScripts::run_for_workspace(
config,
cargo,
progress,
- toolchain,
- sysroot.as_ref().ok(),
+ self.toolchain.as_ref(),
+ self.sysroot.as_ref().ok(),
)
.with_context(|| {
format!("Failed to run build scripts for {}", cargo.workspace_root())
})
}
- ProjectWorkspace::DetachedFile { cargo_script: None, .. }
- | ProjectWorkspace::Json { .. } => Ok(WorkspaceBuildScripts::default()),
+ ProjectWorkspaceKind::DetachedFile { cargo: None, .. }
+ | ProjectWorkspaceKind::Json { .. } => Ok(WorkspaceBuildScripts::default()),
}
}
@@ -557,8 +516,8 @@ impl ProjectWorkspace {
let cargo_ws: Vec<_> = workspaces
.iter()
- .filter_map(|it| match it {
- ProjectWorkspace::Cargo { cargo, .. } => Some(cargo),
+ .filter_map(|it| match &it.kind {
+ ProjectWorkspaceKind::Cargo { cargo, .. } => Some(cargo),
_ => None,
})
.collect();
@@ -572,8 +531,8 @@ impl ProjectWorkspace {
workspaces
.iter()
- .map(|it| match it {
- ProjectWorkspace::Cargo { cargo, .. } => match outputs {
+ .map(|it| match &it.kind {
+ ProjectWorkspaceKind::Cargo { cargo, .. } => match outputs {
Ok(outputs) => Ok(outputs.next().unwrap()),
Err(e) => Err(e.clone()).with_context(|| {
format!("Failed to run build scripts for {}", cargo.workspace_root())
@@ -585,39 +544,33 @@ impl ProjectWorkspace {
}
pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
- match self {
- ProjectWorkspace::Cargo { build_scripts, .. } => *build_scripts = bs,
- _ => {
- always!(bs == WorkspaceBuildScripts::default());
+ match &mut self.kind {
+ ProjectWorkspaceKind::Cargo { build_scripts, .. }
+ | ProjectWorkspaceKind::DetachedFile { cargo: Some((_, build_scripts)), .. } => {
+ *build_scripts = bs
}
+ _ => assert_eq!(bs, WorkspaceBuildScripts::default()),
}
}
- pub fn workspace_definition_path(&self) -> &AbsPath {
- match self {
- ProjectWorkspace::Cargo { cargo, .. } => cargo.workspace_root(),
- ProjectWorkspace::Json { project, .. } => project.path(),
- ProjectWorkspace::DetachedFile { file, .. } => file,
+ pub fn manifest_or_root(&self) -> &AbsPath {
+ match &self.kind {
+ ProjectWorkspaceKind::Cargo { cargo, .. } => cargo.manifest_path(),
+ ProjectWorkspaceKind::Json(project) => project.manifest_or_root(),
+ ProjectWorkspaceKind::DetachedFile { file, .. } => file,
}
}
pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
- match self {
- ProjectWorkspace::Cargo { sysroot: Ok(sysroot), .. }
- | ProjectWorkspace::Json { sysroot: Ok(sysroot), .. }
- | ProjectWorkspace::DetachedFile { sysroot: Ok(sysroot), .. } => {
- sysroot.discover_proc_macro_srv()
- }
- ProjectWorkspace::DetachedFile { .. } => {
- Err(anyhow::format_err!("cannot find proc-macro server, no sysroot was found"))
- }
- ProjectWorkspace::Cargo { cargo, .. } => Err(anyhow::format_err!(
- "cannot find proc-macro-srv, the workspace `{}` is missing a sysroot",
- cargo.workspace_root()
+ match &self.sysroot {
+ Ok(sysroot) => sysroot.discover_proc_macro_srv(),
+ Err(None) => Err(anyhow::format_err!(
+ "cannot find proc-macro server, the workspace `{}` is missing a sysroot",
+ self.manifest_or_root()
)),
- ProjectWorkspace::Json { project, .. } => Err(anyhow::format_err!(
- "cannot find proc-macro-srv, the workspace `{}` is missing a sysroot",
- project.path()
+ Err(Some(e)) => Err(anyhow::format_err!(
+ "cannot find proc-macro server, the workspace `{}` is missing a sysroot: {e}",
+ self.manifest_or_root()
)),
}
}
@@ -626,8 +579,8 @@ impl ProjectWorkspace {
/// The return type contains the path and whether or not
/// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> {
- let mk_sysroot = |sysroot: Result<_, _>| {
- sysroot.into_iter().flat_map(move |sysroot: &Sysroot| {
+ let mk_sysroot = || {
+ self.sysroot.as_ref().into_iter().flat_map(move |sysroot: &Sysroot| {
let mut r = match sysroot.mode() {
SysrootMode::Workspace(ws) => ws
.packages()
@@ -661,15 +614,8 @@ impl ProjectWorkspace {
r
})
};
- match self {
- ProjectWorkspace::Json {
- project,
- sysroot,
- rustc_cfg: _,
- toolchain: _,
- target_layout: _,
- cfg_overrides: _,
- } => project
+ match &self.kind {
+ ProjectWorkspaceKind::Json(project) => project
.crates()
.map(|(_, krate)| PackageRoot {
is_local: krate.is_workspace_member,
@@ -678,17 +624,12 @@ impl ProjectWorkspace {
})
.collect::<FxHashSet<_>>()
.into_iter()
- .chain(mk_sysroot(sysroot.as_ref()))
+ .chain(mk_sysroot())
.collect::<Vec<_>>(),
- ProjectWorkspace::Cargo {
+ ProjectWorkspaceKind::Cargo {
cargo,
- sysroot,
rustc,
- rustc_cfg: _,
- cfg_overrides: _,
build_scripts,
- toolchain: _,
- target_layout: _,
cargo_config_extra_env: _,
} => {
cargo
@@ -729,7 +670,7 @@ impl ProjectWorkspace {
}
PackageRoot { is_local, include, exclude }
})
- .chain(mk_sysroot(sysroot.as_ref()))
+ .chain(mk_sysroot())
.chain(rustc.iter().map(|a| a.as_ref()).flat_map(|(rustc, _)| {
rustc.packages().map(move |krate| PackageRoot {
is_local: false,
@@ -739,18 +680,21 @@ impl ProjectWorkspace {
}))
.collect()
}
- ProjectWorkspace::DetachedFile { file, cargo_script, sysroot, .. } => {
+ ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => {
iter::once(PackageRoot {
is_local: true,
- include: vec![file.clone()],
+ include: vec![file.as_ref().to_owned()],
exclude: Vec::new(),
})
- .chain(cargo_script.iter().flat_map(|cargo| {
+ .chain(cargo_script.iter().flat_map(|(cargo, build_scripts)| {
cargo.packages().map(|pkg| {
let is_local = cargo[pkg].is_local;
let pkg_root = cargo[pkg].manifest.parent().to_path_buf();
let mut include = vec![pkg_root.clone()];
+ let out_dir =
+ build_scripts.get_output(pkg).and_then(|it| it.out_dir.clone());
+ include.extend(out_dir);
// In case target's path is manually set in Cargo.toml to be
// outside the package root, add its parent as an extra include.
@@ -780,28 +724,28 @@ impl ProjectWorkspace {
PackageRoot { is_local, include, exclude }
})
}))
- .chain(mk_sysroot(sysroot.as_ref()))
+ .chain(mk_sysroot())
.collect()
}
}
}
pub fn n_packages(&self) -> usize {
- match self {
- ProjectWorkspace::Json { project, sysroot, .. } => {
- let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages());
+ match &self.kind {
+ ProjectWorkspaceKind::Json(project) => {
+ let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
sysroot_package_len + project.n_crates()
}
- ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => {
+ ProjectWorkspaceKind::Cargo { cargo, rustc, .. } => {
let rustc_package_len =
rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(it, _)| it.packages().len());
- let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages());
+ let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
cargo.packages().len() + sysroot_package_len + rustc_package_len
}
- ProjectWorkspace::DetachedFile { sysroot, cargo_script, .. } => {
- let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages());
+ ProjectWorkspaceKind::DetachedFile { cargo: cargo_script, .. } => {
+ let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
sysroot_package_len
- + cargo_script.as_ref().map_or(1, |cargo| cargo.packages().len())
+ + cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len())
}
}
}
@@ -813,15 +757,9 @@ impl ProjectWorkspace {
) -> (CrateGraph, ProcMacroPaths) {
let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered();
- let ((mut crate_graph, proc_macros), sysroot) = match self {
- ProjectWorkspace::Json {
- project,
- sysroot,
- rustc_cfg,
- toolchain: _,
- target_layout: _,
- cfg_overrides,
- } => (
+ let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
+ let ((mut crate_graph, proc_macros), sysroot) = match kind {
+ ProjectWorkspaceKind::Json(project) => (
project_json_to_crate_graph(
rustc_cfg.clone(),
load,
@@ -832,15 +770,10 @@ impl ProjectWorkspace {
),
sysroot,
),
- ProjectWorkspace::Cargo {
+ ProjectWorkspaceKind::Cargo {
cargo,
- sysroot,
rustc,
- rustc_cfg,
- cfg_overrides,
build_scripts,
- toolchain: _,
- target_layout: _,
cargo_config_extra_env: _,
} => (
cargo_to_crate_graph(
@@ -854,16 +787,8 @@ impl ProjectWorkspace {
),
sysroot,
),
- ProjectWorkspace::DetachedFile {
- file,
- sysroot,
- rustc_cfg,
- toolchain: _,
- target_layout: _,
- cfg_overrides,
- cargo_script,
- } => (
- if let Some(cargo) = cargo_script {
+ ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => (
+ if let Some((cargo, build_scripts)) = cargo_script {
cargo_to_crate_graph(
&mut |path| load(path),
None,
@@ -871,7 +796,7 @@ impl ProjectWorkspace {
sysroot.as_ref().ok(),
rustc_cfg.clone(),
cfg_overrides,
- &WorkspaceBuildScripts::default(),
+ build_scripts,
)
} else {
detached_file_to_crate_graph(
@@ -897,93 +822,60 @@ impl ProjectWorkspace {
}
pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
- match (self, other) {
+ let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides, .. } = self;
+ let Self {
+ kind: o_kind,
+ sysroot: o_sysroot,
+ rustc_cfg: o_rustc_cfg,
+ toolchain: o_toolchain,
+ target_layout: o_target_layout,
+ cfg_overrides: o_cfg_overrides,
+ ..
+ } = other;
+ (match (kind, o_kind) {
(
- Self::Cargo {
+ ProjectWorkspaceKind::Cargo {
cargo,
- sysroot,
rustc,
- rustc_cfg,
- cfg_overrides,
- toolchain,
cargo_config_extra_env,
build_scripts: _,
- target_layout: _,
},
- Self::Cargo {
+ ProjectWorkspaceKind::Cargo {
cargo: o_cargo,
- sysroot: o_sysroot,
rustc: o_rustc,
- rustc_cfg: o_rustc_cfg,
- cfg_overrides: o_cfg_overrides,
- toolchain: o_toolchain,
cargo_config_extra_env: o_cargo_config_extra_env,
build_scripts: _,
- target_layout: _,
},
) => {
cargo == o_cargo
&& rustc == o_rustc
- && rustc_cfg == o_rustc_cfg
- && cfg_overrides == o_cfg_overrides
- && toolchain == o_toolchain
- && sysroot == o_sysroot
&& cargo_config_extra_env == o_cargo_config_extra_env
}
- (
- Self::Json {
- project,
- sysroot,
- rustc_cfg,
- toolchain,
- target_layout: _,
- cfg_overrides,
- },
- Self::Json {
- project: o_project,
- sysroot: o_sysroot,
- rustc_cfg: o_rustc_cfg,
- toolchain: o_toolchain,
- target_layout: _,
- cfg_overrides: o_cfg_overrides,
- },
- ) => {
+ (ProjectWorkspaceKind::Json(project), ProjectWorkspaceKind::Json(o_project)) => {
project == o_project
- && rustc_cfg == o_rustc_cfg
- && sysroot == o_sysroot
- && toolchain == o_toolchain
- && cfg_overrides == o_cfg_overrides
}
(
- Self::DetachedFile {
+ ProjectWorkspaceKind::DetachedFile {
file,
- sysroot,
- rustc_cfg,
- cargo_script,
- toolchain,
- target_layout,
- cfg_overrides,
+ cargo: Some((cargo_script, _)),
+ cargo_config_extra_env,
},
- Self::DetachedFile {
+ ProjectWorkspaceKind::DetachedFile {
file: o_file,
- sysroot: o_sysroot,
- rustc_cfg: o_rustc_cfg,
- cargo_script: o_cargo_script,
- toolchain: o_toolchain,
- target_layout: o_target_layout,
- cfg_overrides: o_cfg_overrides,
+ cargo: Some((o_cargo_script, _)),
+ cargo_config_extra_env: o_cargo_config_extra_env,
},
) => {
file == o_file
- && sysroot == o_sysroot
- && rustc_cfg == o_rustc_cfg
- && toolchain == o_toolchain
- && target_layout == o_target_layout
- && cfg_overrides == o_cfg_overrides
&& cargo_script == o_cargo_script
+ && cargo_config_extra_env == o_cargo_config_extra_env
}
- _ => false,
- }
+ _ => return false,
+ }) && sysroot == o_sysroot
+ && rustc_cfg == o_rustc_cfg
+ && toolchain == o_toolchain
+ && target_layout == o_target_layout
+ && cfg_overrides == o_cfg_overrides
}
/// Returns `true` if the project workspace is [`Json`].
@@ -991,10 +883,11 @@ impl ProjectWorkspace {
/// [`Json`]: ProjectWorkspace::Json
#[must_use]
pub fn is_json(&self) -> bool {
- matches!(self, Self::Json { .. })
+ matches!(self.kind, ProjectWorkspaceKind::Json { .. })
}
}
+#[instrument(skip_all)]
fn project_json_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
load: FileLoader<'_>,
@@ -1294,11 +1187,11 @@ fn cargo_to_crate_graph(
fn detached_file_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
load: FileLoader<'_>,
- detached_file: &AbsPathBuf,
+ detached_file: &ManifestPath,
sysroot: Option<&Sysroot>,
override_cfg: &CfgOverrides,
) -> (CrateGraph, ProcMacroPaths) {
- let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered();
+ let _p = tracing::span!(tracing::Level::INFO, "detached_file_to_crate_graph").entered();
let mut crate_graph = CrateGraph::default();
let (public_deps, _libproc_macro) = match sysroot {
Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load),
@@ -1520,7 +1413,7 @@ impl SysrootPublicDeps {
/// Makes `from` depend on the public sysroot crates.
fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
for (name, krate, prelude) in &self.deps {
- add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude);
+ add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude, true);
}
}
}
@@ -1573,7 +1466,7 @@ fn sysroot_to_crate_graph(
| LangCrateOrigin::Std => pub_deps.push((
CrateName::normalize_dashes(&lang_crate.to_string()),
cid,
- !matches!(lang_crate, LangCrateOrigin::Test),
+ !matches!(lang_crate, LangCrateOrigin::Test | LangCrateOrigin::Alloc),
)),
LangCrateOrigin::ProcMacro => libproc_macro = Some(cid),
LangCrateOrigin::Other => (),
@@ -1674,12 +1567,20 @@ fn add_dep_with_prelude(
name: CrateName,
to: CrateId,
prelude: bool,
+ sysroot: bool,
) {
- add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude))
+ add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, sysroot))
}
fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) {
- add_dep_with_prelude(crate_graph, from, CrateName::new("proc_macro").unwrap(), to, prelude);
+ add_dep_with_prelude(
+ crate_graph,
+ from,
+ CrateName::new("proc_macro").unwrap(),
+ to,
+ prelude,
+ true,
+ );
}
fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {