summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/project-model
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /src/tools/rust-analyzer/crates/project-model
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/project-model')
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs85
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs8
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs21
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs15
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs206
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");