diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/project-model')
6 files changed, 214 insertions, 123 deletions
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs index 6550cf27e..4e5d640f1 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs @@ -15,13 +15,13 @@ use std::{ use cargo_metadata::{camino::Utf8Path, Message}; use la_arena::ArenaMap; -use paths::AbsPathBuf; +use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; use semver::Version; use serde::Deserialize; use crate::{ - cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation, + cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation, InvocationStrategy, Package, }; @@ -67,6 +67,7 @@ impl WorkspaceBuildScripts { let mut cmd = Command::new(toolchain::cargo()); cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]); + cmd.args(&config.extra_args); // --all-targets includes tests, benches and examples in addition to the // default lib and bins. This is an independent concept from the --target @@ -250,7 +251,7 @@ impl WorkspaceBuildScripts { if tracing::enabled!(tracing::Level::INFO) { for package in workspace.packages() { - let package_build_data = &mut outputs[package]; + let package_build_data = &outputs[package]; if !package_build_data.is_unchanged() { tracing::info!( "{}: {:?}", @@ -378,6 +379,84 @@ impl WorkspaceBuildScripts { pub(crate) fn get_output(&self, idx: Package) -> Option<&BuildScriptOutput> { self.outputs.get(idx) } + + pub(crate) fn rustc_crates( + rustc: &CargoWorkspace, + current_dir: &AbsPath, + extra_env: &FxHashMap<String, String>, + ) -> Self { + let mut bs = WorkspaceBuildScripts::default(); + for p in rustc.packages() { + bs.outputs.insert(p, BuildScriptOutput::default()); + } + let res = (|| { + let target_libdir = (|| { + let mut cargo_config = Command::new(toolchain::cargo()); + cargo_config.envs(extra_env); + cargo_config + .current_dir(current_dir) + .args(["rustc", "-Z", "unstable-options", "--print", "target-libdir"]) + .env("RUSTC_BOOTSTRAP", "1"); + if let Ok(it) = utf8_stdout(cargo_config) { + return Ok(it); + } + let mut cmd = Command::new(toolchain::rustc()); + cmd.envs(extra_env); + cmd.args(["--print", "target-libdir"]); + utf8_stdout(cmd) + })()?; + + let target_libdir = AbsPathBuf::try_from(PathBuf::from(target_libdir)) + .map_err(|_| anyhow::format_err!("target-libdir was not an absolute path"))?; + tracing::info!("Loading rustc proc-macro paths from {}", target_libdir.display()); + + let proc_macro_dylibs: Vec<(String, AbsPathBuf)> = std::fs::read_dir(target_libdir)? + .filter_map(|entry| { + let dir_entry = entry.ok()?; + if dir_entry.file_type().ok()?.is_file() { + let path = dir_entry.path(); + tracing::info!("p{:?}", path); + let extension = path.extension()?; + if extension == std::env::consts::DLL_EXTENSION { + let name = path.file_stem()?.to_str()?.split_once('-')?.0.to_owned(); + let path = AbsPathBuf::try_from(path).ok()?; + return Some((name, path)); + } + } + None + }) + .collect(); + for p in rustc.packages() { + let package = &rustc[p]; + if package.targets.iter().any(|&it| rustc[it].is_proc_macro) { + if let Some((_, path)) = proc_macro_dylibs + .iter() + .find(|(name, _)| *name.trim_start_matches("lib") == package.name) + { + bs.outputs[p].proc_macro_dylib_path = Some(path.clone()); + } + } + } + + if tracing::enabled!(tracing::Level::INFO) { + for package in rustc.packages() { + let package_build_data = &bs.outputs[package]; + if !package_build_data.is_unchanged() { + tracing::info!( + "{}: {:?}", + rustc[package].manifest.parent().display(), + package_build_data, + ); + } + } + } + Ok(()) + })(); + if let Err::<_, anyhow::Error>(e) = res { + bs.error = Some(e.to_string()); + } + bs + } } // FIXME: Find a better way to know if it is a dylib. diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index fdc7859eb..01162b1a8 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -50,7 +50,7 @@ impl ops::Index<Target> for CargoWorkspace { /// Describes how to set the rustc source directory. #[derive(Clone, Debug, PartialEq, Eq)] -pub enum RustcSource { +pub enum RustLibSource { /// Explicit path for the rustc source directory. Path(AbsPathBuf), /// Try to automatically detect where the rustc source directory is. @@ -95,16 +95,18 @@ pub struct CargoConfig { /// rustc target pub target: Option<String>, /// Sysroot loading behavior - pub sysroot: Option<RustcSource>, + pub sysroot: Option<RustLibSource>, pub sysroot_src: Option<AbsPathBuf>, /// rustc private crate source - pub rustc_source: Option<RustcSource>, + pub rustc_source: Option<RustLibSource>, /// crates to disable `#[cfg(test)]` on pub unset_test_crates: UnsetTestCrates, /// Invoke `cargo check` through the RUSTC_WRAPPER. pub wrap_rustc_in_build_scripts: bool, /// The command to run instead of `cargo check` for building build scripts. pub run_build_script_command: Option<Vec<String>>, + /// Extra args to pass to the cargo command. + pub extra_args: Vec<String>, /// Extra env vars to set when invoking the cargo command pub extra_env: FxHashMap<String, String>, pub invocation_strategy: InvocationStrategy, diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index 9b6a71db8..70cb71ae3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -44,7 +44,7 @@ pub use crate::{ build_scripts::WorkspaceBuildScripts, cargo_workspace::{ CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency, - RustcSource, Target, TargetData, TargetKind, UnsetTestCrates, + RustLibSource, Target, TargetData, TargetKind, UnsetTestCrates, }, manifest_path::ManifestPath, project_json::{ProjectJson, ProjectJsonData}, diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 328d2fbcf..74e41eda7 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -88,23 +88,17 @@ impl Sysroot { } pub fn discover_with_src_override( - dir: &AbsPath, + current_dir: &AbsPath, extra_env: &FxHashMap<String, String>, src: AbsPathBuf, ) -> Result<Sysroot> { - tracing::debug!("discovering sysroot for {}", dir.display()); - let sysroot_dir = discover_sysroot_dir(dir, extra_env)?; + tracing::debug!("discovering sysroot for {}", current_dir.display()); + let sysroot_dir = discover_sysroot_dir(current_dir, extra_env)?; Ok(Sysroot::load(sysroot_dir, src)) } - pub fn discover_rustc( - cargo_toml: &ManifestPath, - extra_env: &FxHashMap<String, String>, - ) -> Option<ManifestPath> { - tracing::debug!("discovering rustc source for {}", cargo_toml.display()); - let current_dir = cargo_toml.parent(); - let sysroot_dir = discover_sysroot_dir(current_dir, extra_env).ok()?; - get_rustc_src(&sysroot_dir) + pub fn discover_rustc(&self) -> Option<ManifestPath> { + get_rustc_src(&self.root) } pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf) -> Result<Sysroot> { @@ -282,4 +276,7 @@ unwind std_detect test"; -const PROC_MACRO_DEPS: &str = "std"; +// core is required for our builtin derives to work in the proc_macro lib currently +const PROC_MACRO_DEPS: &str = " +std +core"; diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 9e9691d11..3754accbb 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -24,8 +24,8 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr let project_workspace = ProjectWorkspace::Cargo { cargo: cargo_workspace, build_scripts: WorkspaceBuildScripts::default(), - sysroot: None, - rustc: None, + sysroot: Err(None), + rustc: Err(None), rustc_cfg: Vec::new(), cfg_overrides, toolchain: None, @@ -37,7 +37,7 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr fn load_rust_project(file: &str) -> CrateGraph { let data = get_test_json_file(file); let project = rooted_project_json(data); - let sysroot = Some(get_fake_sysroot()); + let sysroot = Ok(get_fake_sysroot()); let project_workspace = ProjectWorkspace::Json { project, sysroot, rustc_cfg: Vec::new() }; to_crate_graph(project_workspace) } @@ -1547,6 +1547,15 @@ fn rust_project_hello_world_project_model() { ), prelude: true, }, + Dependency { + crate_id: CrateId( + 1, + ), + name: CrateName( + "core", + ), + prelude: true, + }, ], proc_macro: Err( "no proc macro loaded for sysroot crate", diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 2a11f1e8e..d1e53e12e 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -17,7 +17,7 @@ use stdx::{always, hash::NoHashHashMap}; use crate::{ build_scripts::BuildScriptOutput, - cargo_workspace::{DepKind, PackageData, RustcSource}, + cargo_workspace::{DepKind, PackageData, RustLibSource}, cfg_flag::CfgFlag, rustc_cfg, sysroot::SysrootCrate, @@ -69,8 +69,8 @@ pub enum ProjectWorkspace { Cargo { cargo: CargoWorkspace, build_scripts: WorkspaceBuildScripts, - sysroot: Option<Sysroot>, - rustc: Option<CargoWorkspace>, + sysroot: Result<Sysroot, Option<String>>, + rustc: Result<(CargoWorkspace, WorkspaceBuildScripts), Option<String>>, /// Holds cfg flags for the current target. We get those by running /// `rustc --print cfg`. /// @@ -82,7 +82,7 @@ pub enum ProjectWorkspace { target_layout: Result<String, String>, }, /// Project workspace was manually specified using a `rust-project.json` file. - Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, + Json { project: ProjectJson, sysroot: Result<Sysroot, Option<String>>, rustc_cfg: Vec<CfgFlag> }, // 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. @@ -93,7 +93,11 @@ pub enum ProjectWorkspace { // // /// Project with a set of disjoint files, not belonging to any particular workspace. /// Backed by basic sysroot crates for basic completion and highlighting. - DetachedFiles { files: Vec<AbsPathBuf>, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, + DetachedFiles { + files: Vec<AbsPathBuf>, + sysroot: Result<Sysroot, Option<String>>, + rustc_cfg: Vec<CfgFlag>, + }, } impl fmt::Debug for ProjectWorkspace { @@ -113,10 +117,10 @@ impl fmt::Debug for ProjectWorkspace { .debug_struct("Cargo") .field("root", &cargo.workspace_root().file_name()) .field("n_packages", &cargo.packages().len()) - .field("sysroot", &sysroot.is_some()) + .field("sysroot", &sysroot.is_ok()) .field( "n_rustc_compiler_crates", - &rustc.as_ref().map_or(0, |rc| rc.packages().len()), + &rustc.as_ref().map_or(0, |(rc, _)| rc.packages().len()), ) .field("n_rustc_cfg", &rustc_cfg.len()) .field("n_cfg_overrides", &cfg_overrides.len()) @@ -126,7 +130,7 @@ impl fmt::Debug for ProjectWorkspace { ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { let mut debug_struct = f.debug_struct("Json"); debug_struct.field("n_crates", &project.n_crates()); - if let Some(sysroot) = sysroot { + if let Ok(sysroot) = sysroot { debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); } debug_struct.field("n_rustc_cfg", &rustc_cfg.len()); @@ -135,7 +139,7 @@ impl fmt::Debug for ProjectWorkspace { ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => f .debug_struct("DetachedFiles") .field("n_files", &files.len()) - .field("sysroot", &sysroot.is_some()) + .field("sysroot", &sysroot.is_ok()) .field("n_rustc_cfg", &rustc_cfg.len()) .finish(), } @@ -191,85 +195,81 @@ impl ProjectWorkspace { let cargo = CargoWorkspace::new(meta); let sysroot = match (&config.sysroot, &config.sysroot_src) { - (Some(RustcSource::Path(path)), None) => { - match Sysroot::with_sysroot_dir(path.clone()) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!(%e, "Failed to find sysroot at {}.", path.display()); - None - } - } + (Some(RustLibSource::Path(path)), None) => { + Sysroot::with_sysroot_dir(path.clone()).map_err(|e| { + Some(format!("Failed to find sysroot at {}:{e}", path.display())) + }) } - (Some(RustcSource::Discover), None) => { - match Sysroot::discover(cargo_toml.parent(), &config.extra_env) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!( - %e, - "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?", - cargo_toml.display() - ); - None - } - } + (Some(RustLibSource::Discover), None) => { + Sysroot::discover(cargo_toml.parent(), &config.extra_env).map_err(|e| { + Some(format!("Failed to find sysroot for Cargo.toml file {}. Is rust-src installed? {e}", cargo_toml.display())) + }) } - (Some(RustcSource::Path(sysroot)), Some(sysroot_src)) => { - Some(Sysroot::load(sysroot.clone(), sysroot_src.clone())) + (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => { + Ok(Sysroot::load(sysroot.clone(), sysroot_src.clone())) } - (Some(RustcSource::Discover), Some(sysroot_src)) => { - match Sysroot::discover_with_src_override( + (Some(RustLibSource::Discover), Some(sysroot_src)) => { + Sysroot::discover_with_src_override( cargo_toml.parent(), &config.extra_env, sysroot_src.clone(), - ) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!( - %e, - "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?", - cargo_toml.display() - ); - None - } - } + ).map_err(|e| { + Some(format!("Failed to find sysroot for Cargo.toml file {}. Is rust-src installed? {e}", cargo_toml.display())) + }) } - (None, _) => None, + (None, _) => Err(None), }; - if let Some(sysroot) = &sysroot { - tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); + if let Ok(sysroot) = &sysroot { + tracing::info!(workspace = %cargo_toml.display(), src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); } let rustc_dir = match &config.rustc_source { - Some(RustcSource::Path(path)) => ManifestPath::try_from(path.clone()).ok(), - Some(RustcSource::Discover) => { - Sysroot::discover_rustc(&cargo_toml, &config.extra_env) + Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone()) + .map_err(|p| { + Some(format!("rustc source path is not absolute: {}", p.display())) + }), + Some(RustLibSource::Discover) => { + sysroot.as_ref().ok().and_then(Sysroot::discover_rustc).ok_or_else(|| { + Some(format!("Failed to discover rustc source for sysroot.")) + }) } - None => None, + None => Err(None), }; - if let Some(rustc_dir) = &rustc_dir { - tracing::info!(rustc_dir = %rustc_dir.display(), "Using rustc source"); - } - let rustc = match rustc_dir { - Some(rustc_dir) => match CargoWorkspace::fetch_metadata( + let rustc = rustc_dir.and_then(|rustc_dir| { + tracing::info!(workspace = %cargo_toml.display(), rustc_dir = %rustc_dir.display(), "Using rustc source"); + match CargoWorkspace::fetch_metadata( &rustc_dir, cargo_toml.parent(), - config, + &CargoConfig { + features: crate::CargoFeatures::default(), + ..config.clone() + }, progress, ) { - Ok(meta) => Some(CargoWorkspace::new(meta)), + Ok(meta) => { + let workspace = CargoWorkspace::new(meta); + let buildscripts = WorkspaceBuildScripts::rustc_crates( + &workspace, + cargo_toml.parent(), + &config.extra_env, + ); + Ok((workspace, buildscripts)) + } Err(e) => { tracing::error!( %e, "Failed to read Cargo metadata from rustc source at {}", rustc_dir.display() ); - None + Err(Some(format!( + "Failed to read Cargo metadata from rustc source at {}: {e}", + rustc_dir.display()) + )) } - }, - None => None, - }; + } + }); let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), &config.extra_env); @@ -305,12 +305,12 @@ impl ProjectWorkspace { extra_env: &FxHashMap<String, String>, ) -> ProjectWorkspace { let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) { - (Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)), + (Some(sysroot), Some(sysroot_src)) => Ok(Sysroot::load(sysroot, sysroot_src)), (Some(sysroot), None) => { // assume sysroot is structured like rustup's and guess `sysroot_src` let sysroot_src = sysroot.join("lib").join("rustlib").join("src").join("rust").join("library"); - Some(Sysroot::load(sysroot, sysroot_src)) + Ok(Sysroot::load(sysroot, sysroot_src)) } (None, Some(sysroot_src)) => { // assume sysroot is structured like rustup's and guess `sysroot` @@ -318,11 +318,11 @@ impl ProjectWorkspace { for _ in 0..5 { sysroot.pop(); } - Some(Sysroot::load(sysroot, sysroot_src)) + Ok(Sysroot::load(sysroot, sysroot_src)) } - (None, None) => None, + (None, None) => Err(None), }; - if let Some(sysroot) = &sysroot { + if let Ok(sysroot) = &sysroot { tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); } @@ -335,33 +335,23 @@ impl ProjectWorkspace { config: &CargoConfig, ) -> Result<ProjectWorkspace> { let sysroot = match &config.sysroot { - Some(RustcSource::Path(path)) => match Sysroot::with_sysroot_dir(path.clone()) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!(%e, "Failed to find sysroot at {}.", path.display()); - None - } - }, - Some(RustcSource::Discover) => { + Some(RustLibSource::Path(path)) => Sysroot::with_sysroot_dir(path.clone()) + .map_err(|e| Some(format!("Failed to find sysroot at {}:{e}", path.display()))), + Some(RustLibSource::Discover) => { let dir = &detached_files .first() .and_then(|it| it.parent()) .ok_or_else(|| format_err!("No detached files to load"))?; - match Sysroot::discover(dir, &config.extra_env) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!( - %e, - "Failed to find sysroot for {}. Is rust-src installed?", - dir.display() - ); - None - } - } + Sysroot::discover(dir, &config.extra_env).map_err(|e| { + Some(format!( + "Failed to find sysroot for {}. Is rust-src installed? {e}", + dir.display() + )) + }) } - None => None, + None => Err(None), }; - if let Some(sysroot) = &sysroot { + if let Ok(sysroot) = &sysroot { tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); } let rustc_cfg = rustc_cfg::get(None, None, &Default::default()); @@ -442,10 +432,18 @@ impl ProjectWorkspace { } } + pub fn workspace_definition_path(&self) -> Option<&AbsPath> { + match self { + ProjectWorkspace::Cargo { cargo, .. } => Some(cargo.workspace_root()), + ProjectWorkspace::Json { project, .. } => Some(project.path()), + ProjectWorkspace::DetachedFiles { .. } => None, + } + } + pub fn find_sysroot_proc_macro_srv(&self) -> Option<AbsPathBuf> { match self { - ProjectWorkspace::Cargo { sysroot: Some(sysroot), .. } - | ProjectWorkspace::Json { sysroot: Some(sysroot), .. } => { + ProjectWorkspace::Cargo { sysroot: Ok(sysroot), .. } + | ProjectWorkspace::Json { sysroot: Ok(sysroot), .. } => { let standalone_server_name = format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX); ["libexec", "lib"] @@ -461,7 +459,7 @@ 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: Option<&Sysroot>, project_root: Option<&AbsPath>| { + let mk_sysroot = |sysroot: Result<&Sysroot, _>, project_root: Option<&AbsPath>| { sysroot.map(|sysroot| PackageRoot { // mark the sysroot as mutable if it is located inside of the project is_local: project_root @@ -531,7 +529,7 @@ impl ProjectWorkspace { PackageRoot { is_local, include, exclude } }) .chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root()))) - .chain(rustc.iter().flat_map(|rustc| { + .chain(rustc.iter().flat_map(|(rustc, _)| { rustc.packages().map(move |krate| PackageRoot { is_local: false, include: vec![rustc[krate].manifest.parent().to_path_buf()], @@ -559,7 +557,7 @@ impl ProjectWorkspace { sysroot_package_len + project.n_crates() } ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => { - let rustc_package_len = rustc.as_ref().map_or(0, |it| it.packages().len()); + let rustc_package_len = rustc.as_ref().map_or(0, |(it, _)| it.packages().len()); let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.crates().len()); cargo.packages().len() + sysroot_package_len + rustc_package_len } @@ -584,7 +582,7 @@ impl ProjectWorkspace { load_proc_macro, load, project, - sysroot.as_ref(), + sysroot.as_ref().ok(), extra_env, Err("rust-project.json projects have no target layout set".into()), ), @@ -600,9 +598,9 @@ impl ProjectWorkspace { } => cargo_to_crate_graph( load_proc_macro, load, - rustc, + rustc.as_ref().ok(), cargo, - sysroot.as_ref(), + sysroot.as_ref().ok(), rustc_cfg.clone(), cfg_overrides, build_scripts, @@ -616,7 +614,7 @@ impl ProjectWorkspace { rustc_cfg.clone(), load, files, - sysroot, + sysroot.as_ref().ok(), Err("detached file projects have no target layout set".into()), ) } @@ -778,7 +776,7 @@ fn project_json_to_crate_graph( fn cargo_to_crate_graph( load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult, load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, - rustc: &Option<CargoWorkspace>, + rustc: Option<&(CargoWorkspace, WorkspaceBuildScripts)>, cargo: &CargoWorkspace, sysroot: Option<&Sysroot>, rustc_cfg: Vec<CfgFlag>, @@ -924,7 +922,7 @@ fn cargo_to_crate_graph( if has_private { // If the user provided a path to rustc sources, we add all the rustc_private crates // and create dependencies on them for the crates which opt-in to that - if let Some(rustc_workspace) = rustc { + if let Some((rustc_workspace, rustc_build_scripts)) = rustc { handle_rustc_crates( &mut crate_graph, &mut pkg_to_lib_crate, @@ -937,7 +935,13 @@ fn cargo_to_crate_graph( &pkg_crates, &cfg_options, override_cfg, - build_scripts, + if rustc_workspace.workspace_root() == cargo.workspace_root() { + // the rustc workspace does not use the installed toolchain's proc-macro server + // so we need to make sure we don't use the pre compiled proc-macros there either + build_scripts + } else { + rustc_build_scripts + }, target_layout, ); } @@ -949,7 +953,7 @@ fn detached_files_to_crate_graph( rustc_cfg: Vec<CfgFlag>, load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, detached_files: &[AbsPathBuf], - sysroot: &Option<Sysroot>, + sysroot: Option<&Sysroot>, target_layout: TargetLayoutLoadResult, ) -> CrateGraph { let _p = profile::span("detached_files_to_crate_graph"); |