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.rs | 535 |
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) { |