Unnamed repository; edit this file 'description' to name the repository.
Allow sysroots to only consist of the source root dir
Lukas Wirth 2024-05-24
parent 5717622 · commit bd37e27
-rw-r--r--crates/hir-ty/src/layout/tests.rs4
-rw-r--r--crates/project-model/src/build_scripts.rs14
-rw-r--r--crates/project-model/src/cargo_workspace.rs14
-rw-r--r--crates/project-model/src/env.rs4
-rw-r--r--crates/project-model/src/rustc_cfg.rs8
-rw-r--r--crates/project-model/src/sysroot.rs204
-rw-r--r--crates/project-model/src/target_data_layout.rs6
-rw-r--r--crates/project-model/src/tests.rs13
-rw-r--r--crates/project-model/src/workspace.rs266
-rw-r--r--crates/rust-analyzer/src/cli/rustc_tests.rs6
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs6
-rw-r--r--crates/rust-analyzer/src/lsp/ext.rs1
-rw-r--r--crates/rust-analyzer/src/reload.rs73
-rw-r--r--crates/rust-analyzer/tests/crate_graph.rs4
-rw-r--r--crates/rust-analyzer/tests/slow-tests/main.rs6
-rw-r--r--docs/dev/lsp-extensions.md2
-rw-r--r--editors/code/src/ctx.ts6
-rw-r--r--editors/code/src/lsp_ext.ts1
18 files changed, 277 insertions, 361 deletions
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 6c1eccb75e..392bda51b5 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -1,7 +1,7 @@
use chalk_ir::{AdtId, TyKind};
use either::Either;
use hir_def::db::DefDatabase;
-use project_model::target_data_layout::RustcDataLayoutConfig;
+use project_model::{target_data_layout::RustcDataLayoutConfig, Sysroot};
use rustc_hash::FxHashMap;
use test_fixture::WithFixture;
use triomphe::Arc;
@@ -17,7 +17,7 @@ mod closure;
fn current_machine_data_layout() -> String {
project_model::target_data_layout::get(
- RustcDataLayoutConfig::Rustc(None),
+ RustcDataLayoutConfig::Rustc(&Sysroot::empty()),
None,
&FxHashMap::default(),
)
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index 8e1f7fdcde..d2f423590e 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -65,7 +65,7 @@ impl WorkspaceBuildScripts {
allowed_features: &FxHashSet<String>,
manifest_path: &ManifestPath,
toolchain: Option<&Version>,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> io::Result<Command> {
const RUST_1_75: Version = Version::new(1, 75, 0);
let mut cmd = match config.run_build_script_command.as_deref() {
@@ -75,7 +75,7 @@ impl WorkspaceBuildScripts {
cmd
}
_ => {
- let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+ let mut cmd = sysroot.tool(Tool::Cargo);
cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
cmd.args(&config.extra_args);
@@ -149,7 +149,7 @@ impl WorkspaceBuildScripts {
workspace: &CargoWorkspace,
progress: &dyn Fn(String),
toolchain: Option<&Version>,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> io::Result<WorkspaceBuildScripts> {
let current_dir = match &config.invocation_location {
InvocationLocation::Root(root) if config.run_build_script_command.is_some() => {
@@ -195,7 +195,7 @@ impl WorkspaceBuildScripts {
// This is not gonna be used anyways, so just construct a dummy here
&ManifestPath::try_from(workspace_root.clone()).unwrap(),
None,
- None,
+ &Sysroot::empty(),
)?;
// NB: Cargo.toml could have been modified between `cargo metadata` and
// `cargo check`. We shouldn't assume that package ids we see here are
@@ -412,7 +412,7 @@ impl WorkspaceBuildScripts {
rustc: &CargoWorkspace,
current_dir: &AbsPath,
extra_env: &FxHashMap<String, String>,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> Self {
let mut bs = WorkspaceBuildScripts::default();
for p in rustc.packages() {
@@ -420,7 +420,7 @@ impl WorkspaceBuildScripts {
}
let res = (|| {
let target_libdir = (|| {
- let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+ let mut cargo_config = sysroot.tool(Tool::Cargo);
cargo_config.envs(extra_env);
cargo_config
.current_dir(current_dir)
@@ -429,7 +429,7 @@ impl WorkspaceBuildScripts {
if let Ok(it) = utf8_stdout(cargo_config) {
return Ok(it);
}
- let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
+ let mut cmd = sysroot.tool(Tool::Rustc);
cmd.envs(extra_env);
cmd.args(["--print", "target-libdir"]);
utf8_stdout(cmd)
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 9955f2687c..632ba1cacf 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -258,12 +258,12 @@ impl CargoWorkspace {
cargo_toml: &ManifestPath,
current_dir: &AbsPath,
config: &CargoConfig,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
progress: &dyn Fn(String),
) -> anyhow::Result<cargo_metadata::Metadata> {
let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
- let cargo = Sysroot::tool(sysroot, Tool::Cargo);
+ let cargo = sysroot.tool(Tool::Cargo);
let mut meta = MetadataCommand::new();
meta.cargo_path(cargo.get_program());
cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default()));
@@ -536,7 +536,7 @@ impl CargoWorkspace {
fn find_list_of_build_targets(
config: &CargoConfig,
cargo_toml: &ManifestPath,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> Vec<String> {
if let Some(target) = &config.target {
return [target.into()].to_vec();
@@ -553,9 +553,9 @@ fn find_list_of_build_targets(
fn rustc_discover_host_triple(
cargo_toml: &ManifestPath,
extra_env: &FxHashMap<String, String>,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> Option<String> {
- let mut rustc = Sysroot::tool(sysroot, Tool::Rustc);
+ let mut rustc = sysroot.tool(Tool::Rustc);
rustc.envs(extra_env);
rustc.current_dir(cargo_toml.parent()).arg("-vV");
tracing::debug!("Discovering host platform by {:?}", rustc);
@@ -581,9 +581,9 @@ fn rustc_discover_host_triple(
fn cargo_config_build_target(
cargo_toml: &ManifestPath,
extra_env: &FxHashMap<String, String>,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> Vec<String> {
- let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+ let mut cargo_config = sysroot.tool(Tool::Cargo);
cargo_config.envs(extra_env);
cargo_config
.current_dir(cargo_toml.parent())
diff --git a/crates/project-model/src/env.rs b/crates/project-model/src/env.rs
index 5520cdaff6..88fb10a68c 100644
--- a/crates/project-model/src/env.rs
+++ b/crates/project-model/src/env.rs
@@ -62,9 +62,9 @@ pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: Targe
pub(crate) fn cargo_config_env(
manifest: &ManifestPath,
extra_env: &FxHashMap<String, String>,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
) -> FxHashMap<String, String> {
- let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+ let mut cargo_config = sysroot.tool(Tool::Cargo);
cargo_config.envs(extra_env);
cargo_config
.current_dir(manifest.parent())
diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs
index 4f69b2b96f..26499308ce 100644
--- a/crates/project-model/src/rustc_cfg.rs
+++ b/crates/project-model/src/rustc_cfg.rs
@@ -10,10 +10,10 @@ use crate::{cfg::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
pub(crate) enum RustcCfgConfig<'a> {
/// Use `rustc --print cfg`, either from with the binary from the sysroot or by discovering via
/// [`toolchain::rustc`].
- Rustc(Option<&'a Sysroot>),
+ Rustc(&'a Sysroot),
/// Use `cargo --print cfg`, either from with the binary from the sysroot or by discovering via
/// [`toolchain::cargo`].
- Cargo(Option<&'a Sysroot>, &'a ManifestPath),
+ Cargo(&'a Sysroot, &'a ManifestPath),
}
pub(crate) fn get(
@@ -65,7 +65,7 @@ fn get_rust_cfgs(
) -> anyhow::Result<String> {
let sysroot = match config {
RustcCfgConfig::Cargo(sysroot, cargo_toml) => {
- let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+ let mut cmd = sysroot.tool(Tool::Cargo);
cmd.envs(extra_env);
cmd.current_dir(cargo_toml.parent())
@@ -86,7 +86,7 @@ fn get_rust_cfgs(
RustcCfgConfig::Rustc(sysroot) => sysroot,
};
- let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
+ let mut cmd = sysroot.tool(Tool::Rustc);
cmd.envs(extra_env);
cmd.args(["--print", "cfg", "-O"]);
if let Some(target) = target {
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index e6bbe6ede8..653e7157bc 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -4,7 +4,7 @@
//! but we can't process `.rlib` and need source code instead. The source code
//! is typically installed with `rustup component add rust-src` command.
-use std::{env, fs, ops, process::Command, sync::Arc};
+use std::{env, fs, ops, process::Command};
use anyhow::{format_err, Result};
use base_db::CrateName;
@@ -16,30 +16,19 @@ use toolchain::{probe_for_binary, Tool};
use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath};
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Sysroot {
- root: AbsPathBuf,
- src_root: Option<Result<AbsPathBuf, Arc<anyhow::Error>>>,
+ root: Option<AbsPathBuf>,
+ src_root: Option<AbsPathBuf>,
mode: SysrootMode,
-}
-
-impl Eq for Sysroot {}
-impl PartialEq for Sysroot {
- fn eq(&self, other: &Self) -> bool {
- self.root == other.root
- && self.mode == other.mode
- && match (&self.src_root, &other.src_root) {
- (Some(Ok(this)), Some(Ok(other))) => this == other,
- (None, None) | (Some(Err(_)), Some(Err(_))) => true,
- _ => false,
- }
- }
+ error: Option<String>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum SysrootMode {
Workspace(CargoWorkspace),
Stitched(Stitched),
+ Empty,
}
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -89,70 +78,40 @@ pub(crate) struct SysrootCrateData {
}
impl Sysroot {
+ pub const fn empty() -> Sysroot {
+ Sysroot { root: None, src_root: None, mode: SysrootMode::Empty, error: None }
+ }
+
/// Returns sysroot "root" directory, where `bin/`, `etc/`, `lib/`, `libexec/`
/// subfolder live, like:
/// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu`
- pub fn root(&self) -> &AbsPath {
- &self.root
+ pub fn root(&self) -> Option<&AbsPath> {
+ self.root.as_deref()
}
/// Returns the sysroot "source" directory, where stdlib sources are located, like:
/// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library`
pub fn src_root(&self) -> Option<&AbsPath> {
- self.src_root.as_ref()?.as_deref().ok()
+ self.src_root.as_deref()
}
pub fn is_empty(&self) -> bool {
match &self.mode {
SysrootMode::Workspace(ws) => ws.packages().next().is_none(),
SysrootMode::Stitched(stitched) => stitched.crates.is_empty(),
+ SysrootMode::Empty => true,
}
}
- pub fn loading_warning(&self) -> Option<String> {
- let src_root = match &self.src_root {
- None => return Some(format!("sysroot at `{}` has no library sources", self.root)),
- Some(Ok(src_root)) => src_root,
- Some(Err(e)) => return Some(e.to_string()),
- };
- let has_core = match &self.mode {
- SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
- SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
- };
- if !has_core {
- let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
- " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
- } else {
- " try running `rustup component add rust-src` to possible fix this"
- };
- Some(format!("could not find libcore in loaded sysroot at `{}`{var_note}", src_root,))
- } else {
- None
- }
- }
-
- pub fn check_has_core(&self) -> Result<(), String> {
- let Some(Ok(src_root)) = &self.src_root else { return Ok(()) };
- let has_core = match &self.mode {
- SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
- SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
- };
- if !has_core {
- let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
- " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
- } else {
- " try running `rustup component add rust-src` to possible fix this"
- };
- Err(format!("could not find libcore in loaded sysroot at `{}`{var_note}", src_root,))
- } else {
- Ok(())
- }
+ pub fn error(&self) -> Option<&str> {
+ self.error.as_deref()
}
pub fn num_packages(&self) -> usize {
match &self.mode {
SysrootMode::Workspace(ws) => ws.packages().count(),
SysrootMode::Stitched(c) => c.crates().count(),
+ SysrootMode::Empty => 0,
}
}
@@ -168,63 +127,50 @@ impl Sysroot {
dir: &AbsPath,
extra_env: &FxHashMap<String, String>,
metadata: bool,
- ) -> Result<Sysroot> {
- tracing::debug!("discovering sysroot for {dir}");
- let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
- let sysroot_src_dir =
- discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env);
- Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata))
- }
-
- pub fn discover_no_source(
- dir: &AbsPath,
- extra_env: &FxHashMap<String, String>,
- ) -> Result<Sysroot> {
- tracing::debug!("discovering sysroot for {dir}");
- let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
- let sysroot_src_dir =
- discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env);
- Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), false))
+ ) -> Sysroot {
+ let sysroot_dir = discover_sysroot_dir(dir, extra_env);
+ let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
+ discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env)
+ });
+ Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, metadata)
}
pub fn discover_with_src_override(
current_dir: &AbsPath,
extra_env: &FxHashMap<String, String>,
- src: AbsPathBuf,
+ sysroot_src_dir: AbsPathBuf,
metadata: bool,
- ) -> Result<Sysroot> {
- tracing::debug!("discovering sysroot for {current_dir}");
- let sysroot_dir = discover_sysroot_dir(current_dir, extra_env)?;
- Ok(Sysroot::load(sysroot_dir, Some(Ok(src)), metadata))
+ ) -> Sysroot {
+ let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
+ Sysroot::load_core_check(Some(sysroot_dir), Some(Ok(sysroot_src_dir)), metadata)
}
- pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
- get_rustc_src(&self.root)
+ pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf, metadata: bool) -> Sysroot {
+ let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir)
+ .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}"));
+ Sysroot::load_core_check(Some(Ok(sysroot_dir)), Some(sysroot_src_dir), metadata)
}
- pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf, metadata: bool) -> Result<Sysroot> {
- let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir).ok_or_else(|| {
- format_err!("can't load standard library from sysroot path {sysroot_dir}")
- });
- Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata))
+ pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
+ get_rustc_src(self.root()?)
}
/// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
- pub fn tool(sysroot: Option<&Self>, tool: Tool) -> Command {
- match sysroot {
- Some(sysroot) => {
+ pub fn tool(&self, tool: Tool) -> Command {
+ match self.root() {
+ Some(root) => {
// special case rustc, we can look that up directly in the sysroot's bin folder
// as it should never invoke another cargo binary
if let Tool::Rustc = tool {
if let Some(path) =
- probe_for_binary(sysroot.root.join("bin").join(Tool::Rustc.name()).into())
+ probe_for_binary(root.join("bin").join(Tool::Rustc.name()).into())
{
return Command::new(path);
}
}
let mut cmd = Command::new(tool.prefer_proxy());
- cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(&sysroot.root));
+ cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
cmd
}
_ => Command::new(tool.path()),
@@ -232,35 +178,89 @@ impl Sysroot {
}
pub fn discover_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
+ let Some(root) = self.root() else {
+ return Err(anyhow::format_err!("no sysroot",));
+ };
["libexec", "lib"]
.into_iter()
- .map(|segment| self.root().join(segment).join("rust-analyzer-proc-macro-srv"))
+ .map(|segment| root.join(segment).join("rust-analyzer-proc-macro-srv"))
.find_map(|server_path| probe_for_binary(server_path.into()))
.map(AbsPathBuf::assert)
.ok_or_else(|| {
- anyhow::format_err!("cannot find proc-macro server in sysroot `{}`", self.root())
+ anyhow::format_err!("cannot find proc-macro server in sysroot `{}`", root)
})
}
pub fn load(
- sysroot_dir: AbsPathBuf,
+ sysroot_dir: Option<AbsPathBuf>,
+ sysroot_src_dir: Option<AbsPathBuf>,
+ metadata: bool,
+ ) -> Sysroot {
+ Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), metadata)
+ }
+
+ fn load_core_check(
+ sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
+ sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
+ metadata: bool,
+ ) -> Sysroot {
+ let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, metadata);
+ if sysroot.error.is_none() {
+ if let Some(src_root) = &sysroot.src_root {
+ let has_core = match &sysroot.mode {
+ SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
+ SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
+ SysrootMode::Empty => true,
+ };
+ if !has_core {
+ let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
+ " (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
+ } else {
+ ", try running `rustup component add rust-src` to possibly fix this"
+ };
+ sysroot.error = Some(format!(
+ "sysroot at `{}` is missing a `core` library{var_note}",
+ src_root,
+ ));
+ }
+ }
+ }
+ sysroot
+ }
+
+ fn load_(
+ sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
metadata: bool,
) -> Sysroot {
+ let sysroot_dir = match sysroot_dir {
+ Some(Ok(sysroot_dir)) => Some(sysroot_dir),
+ Some(Err(e)) => {
+ return Sysroot {
+ root: None,
+ src_root: None,
+ mode: SysrootMode::Empty,
+ error: Some(e.to_string()),
+ }
+ }
+ None => None,
+ };
let sysroot_src_dir = match sysroot_src_dir {
Some(Ok(sysroot_src_dir)) => sysroot_src_dir,
Some(Err(e)) => {
return Sysroot {
root: sysroot_dir,
- src_root: Some(Err(Arc::new(e))),
- mode: SysrootMode::Stitched(Stitched { crates: Arena::default() }),
+ src_root: None,
+ mode: SysrootMode::Empty,
+ error: Some(e.to_string()),
}
}
None => {
return Sysroot {
root: sysroot_dir,
src_root: None,
- mode: SysrootMode::Stitched(Stitched { crates: Arena::default() }),
+ mode: SysrootMode::Empty,
+ error: None,
}
}
};
@@ -284,7 +284,7 @@ impl Sysroot {
&sysroot_cargo_toml,
&current_dir,
&cargo_config,
- None,
+ &Sysroot::empty(),
&|_| (),
)
.map_err(|e| {
@@ -368,8 +368,9 @@ impl Sysroot {
let cargo_workspace = CargoWorkspace::new(res, sysroot_cargo_toml);
Some(Sysroot {
root: sysroot_dir.clone(),
- src_root: Some(Ok(sysroot_src_dir.clone())),
+ src_root: Some(sysroot_src_dir.clone()),
mode: SysrootMode::Workspace(cargo_workspace),
+ error: None,
})
})();
if let Some(sysroot) = sysroot {
@@ -420,8 +421,9 @@ impl Sysroot {
}
Sysroot {
root: sysroot_dir,
- src_root: Some(Ok(sysroot_src_dir)),
+ src_root: Some(sysroot_src_dir),
mode: SysrootMode::Stitched(stitched),
+ error: None,
}
}
}
diff --git a/crates/project-model/src/target_data_layout.rs b/crates/project-model/src/target_data_layout.rs
index 4e810a0232..8a8a2d3255 100644
--- a/crates/project-model/src/target_data_layout.rs
+++ b/crates/project-model/src/target_data_layout.rs
@@ -9,10 +9,10 @@ use crate::{utf8_stdout, ManifestPath, Sysroot};
pub enum RustcDataLayoutConfig<'a> {
/// Use `rustc --print target-spec-json`, either from with the binary from the sysroot or by discovering via
/// [`toolchain::rustc`].
- Rustc(Option<&'a Sysroot>),
+ Rustc(&'a Sysroot),
/// Use `cargo --print target-spec-json`, either from with the binary from the sysroot or by discovering via
/// [`toolchain::cargo`].
- Cargo(Option<&'a Sysroot>, &'a ManifestPath),
+ Cargo(&'a Sysroot, &'a ManifestPath),
}
pub fn get(
@@ -28,7 +28,7 @@ pub fn get(
};
let sysroot = match config {
RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => {
- let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+ let mut cmd = sysroot.tool(Tool::Cargo);
cmd.envs(extra_env);
cmd.current_dir(cargo_toml.parent())
.args([
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 3d5a934fc9..a6730863d6 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -34,7 +34,7 @@ fn load_cargo_with_overrides(
cargo_config_extra_env: Default::default(),
},
cfg_overrides,
- sysroot: Err(None),
+ sysroot: Sysroot::empty(),
rustc_cfg: Vec::new(),
toolchain: None,
target_layout: Err("target_data_layout not loaded".into()),
@@ -57,7 +57,7 @@ fn load_cargo_with_fake_sysroot(
rustc: Err(None),
cargo_config_extra_env: Default::default(),
},
- sysroot: Ok(get_fake_sysroot()),
+ sysroot: get_fake_sysroot(),
rustc_cfg: Vec::new(),
cfg_overrides: Default::default(),
toolchain: None,
@@ -77,7 +77,7 @@ fn load_cargo_with_fake_sysroot(
fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
let data = get_test_json_file(file);
let project = rooted_project_json(data);
- let sysroot = Ok(get_fake_sysroot());
+ let sysroot = get_fake_sysroot();
let project_workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::Json(project),
sysroot,
@@ -144,7 +144,7 @@ fn get_fake_sysroot() -> Sysroot {
// fake sysroot, so we give them both the same path:
let sysroot_dir = AbsPathBuf::assert(sysroot_path);
let sysroot_src_dir = sysroot_dir.clone();
- Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
+ Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), false)
}
fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
@@ -281,12 +281,11 @@ fn smoke_test_real_sysroot_cargo() {
let manifest_path =
ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
- let sysroot = Ok(Sysroot::discover(
+ let sysroot = Sysroot::discover(
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
&Default::default(),
true,
- )
- .unwrap());
+ );
let project_workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 85621444e3..0d2174073a 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -48,7 +48,7 @@ pub struct PackageRoot {
pub struct ProjectWorkspace {
pub kind: ProjectWorkspaceKind,
/// The sysroot loaded for this workspace.
- pub sysroot: Result<Sysroot, Option<String>>,
+ pub sysroot: Sysroot,
/// 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
@@ -112,7 +112,7 @@ 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_ok())
+ .field("n_sysroot_crates", &sysroot.num_packages())
.field(
"n_rustc_compiler_crates",
&rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(rc, _)| rc.packages().len()),
@@ -125,11 +125,9 @@ impl fmt::Debug for ProjectWorkspace {
.finish(),
ProjectWorkspaceKind::Json(project) => {
let mut debug_struct = f.debug_struct("Json");
- debug_struct.field("n_crates", &project.n_crates());
- if let Ok(sysroot) = sysroot {
- debug_struct.field("n_sysroot_crates", &sysroot.num_packages());
- }
debug_struct
+ .field("n_crates", &project.n_crates())
+ .field("n_sysroot_crates", &sysroot.num_packages())
.field("n_rustc_cfg", &rustc_cfg.len())
.field("toolchain", &toolchain)
.field("data_layout", &target_layout)
@@ -144,7 +142,7 @@ impl fmt::Debug for ProjectWorkspace {
.debug_struct("DetachedFiles")
.field("file", &file)
.field("cargo_script", &cargo_script.is_some())
- .field("sysroot", &sysroot.is_ok())
+ .field("n_sysroot_crates", &sysroot.num_packages())
.field("cargo_script", &cargo_script.is_some())
.field("n_rustc_cfg", &rustc_cfg.len())
.field("toolchain", &toolchain)
@@ -158,7 +156,7 @@ impl fmt::Debug for ProjectWorkspace {
fn get_toolchain_version(
current_dir: &AbsPath,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
tool: Tool,
extra_env: &FxHashMap<String, String>,
prefix: &str,
@@ -213,41 +211,37 @@ impl ProjectWorkspace {
}
ProjectManifest::CargoToml(cargo_toml) => {
let sysroot = match (&config.sysroot, &config.sysroot_src) {
- (Some(RustLibSource::Path(path)), None) => {
- 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), None) => {
- Sysroot::discover(cargo_toml.parent(), &config.extra_env, config.sysroot_query_metadata).map_err(|e| {
- Some(format!("Failed to find sysroot for Cargo.toml file {cargo_toml}. Is rust-src installed? {e}"))
- })
- }
- (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => {
- Ok(Sysroot::load(sysroot.clone(), Some(Ok(sysroot_src.clone())), config.sysroot_query_metadata))
- }
+ (Some(RustLibSource::Discover), None) => Sysroot::discover(
+ cargo_toml.parent(),
+ &config.extra_env,
+ config.sysroot_query_metadata,
+ ),
(Some(RustLibSource::Discover), Some(sysroot_src)) => {
Sysroot::discover_with_src_override(
cargo_toml.parent(),
&config.extra_env,
- sysroot_src.clone(), config.sysroot_query_metadata,
- ).map_err(|e| {
- Some(format!("Failed to find sysroot for Cargo.toml file {cargo_toml}. Is rust-src installed? {e}"))
- })
+ sysroot_src.clone(),
+ config.sysroot_query_metadata,
+ )
}
- (None, _) => Err(None),
+ (Some(RustLibSource::Path(path)), None) => Sysroot::discover_sysroot_src_dir(
+ path.clone(),
+ config.sysroot_query_metadata,
+ ),
+ (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => Sysroot::load(
+ Some(sysroot.clone()),
+ Some(sysroot_src.clone()),
+ config.sysroot_query_metadata,
+ ),
+ (None, _) => Sysroot::empty(),
};
- let sysroot_ref = sysroot.as_ref().ok();
-
- if let Ok(sysroot) = &sysroot {
- tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = %sysroot.root(), "Using sysroot");
- }
+ tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
let rustc_dir = match &config.rustc_source {
Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
.map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
Some(RustLibSource::Discover) => {
- sysroot_ref.and_then(Sysroot::discover_rustc_src).ok_or_else(|| {
+ sysroot.discover_rustc_src().ok_or_else(|| {
Some("Failed to discover rustc source for sysroot.".to_owned())
})
}
@@ -263,7 +257,7 @@ impl ProjectWorkspace {
features: crate::CargoFeatures::default(),
..config.clone()
},
- sysroot_ref,
+ &sysroot,
progress,
) {
Ok(meta) => {
@@ -272,7 +266,7 @@ impl ProjectWorkspace {
&workspace,
cargo_toml.parent(),
&config.extra_env,
- sysroot_ref
+ &sysroot
);
Ok(Box::new((workspace, buildscripts)))
}
@@ -290,7 +284,7 @@ impl ProjectWorkspace {
let toolchain = get_toolchain_version(
cargo_toml.parent(),
- sysroot_ref,
+ &sysroot,
Tool::Cargo,
&config.extra_env,
"cargo ",
@@ -298,12 +292,12 @@ impl ProjectWorkspace {
let rustc_cfg = rustc_cfg::get(
config.target.as_deref(),
&config.extra_env,
- RustcCfgConfig::Cargo(sysroot_ref, cargo_toml),
+ RustcCfgConfig::Cargo(&sysroot, cargo_toml),
);
let cfg_overrides = config.cfg_overrides.clone();
let data_layout = target_data_layout::get(
- RustcDataLayoutConfig::Cargo(sysroot_ref, cargo_toml),
+ RustcDataLayoutConfig::Cargo(&sysroot, cargo_toml),
config.target.as_deref(),
&config.extra_env,
);
@@ -315,7 +309,7 @@ impl ProjectWorkspace {
cargo_toml,
cargo_toml.parent(),
config,
- sysroot_ref,
+ &sysroot,
progress,
)
.with_context(|| {
@@ -326,7 +320,7 @@ impl ProjectWorkspace {
let cargo = CargoWorkspace::new(meta, cargo_toml.clone());
let cargo_config_extra_env =
- cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref);
+ cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo,
@@ -354,32 +348,13 @@ impl ProjectWorkspace {
extra_env: &FxHashMap<String, String>,
cfg_overrides: &CfgOverrides,
) -> ProjectWorkspace {
- let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
- (Some(sysroot), Some(sysroot_src)) => {
- Ok(Sysroot::load(sysroot, Some(Ok(sysroot_src)), false))
- }
- (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");
- Ok(Sysroot::load(sysroot, Some(Ok(sysroot_src)), false))
- }
- (None, Some(sysroot_src)) => {
- // assume sysroot is structured like rustup's and guess `sysroot`
- let mut sysroot = sysroot_src.clone();
- for _ in 0..5 {
- sysroot.pop();
- }
- Ok(Sysroot::load(sysroot, Some(Ok(sysroot_src)), false))
- }
- (None, None) => Err(None),
- };
- let sysroot_ref = sysroot.as_ref().ok();
- let cfg_config = RustcCfgConfig::Rustc(sysroot_ref);
- let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref);
+ let sysroot =
+ Sysroot::load(project_json.sysroot.clone(), project_json.sysroot_src.clone(), false);
+ let cfg_config = RustcCfgConfig::Rustc(&sysroot);
+ let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot);
let toolchain = match get_toolchain_version(
project_json.path(),
- sysroot_ref,
+ &sysroot,
Tool::Rustc,
extra_env,
"rustc ",
@@ -410,24 +385,16 @@ impl 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}")))
+ Sysroot::discover_sysroot_src_dir(path.clone(), config.sysroot_query_metadata)
+ }
+ Some(RustLibSource::Discover) => {
+ Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
}
- 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),
+ None => Sysroot::empty(),
};
- let sysroot_ref = sysroot.as_ref().ok();
let toolchain =
- match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ")
- {
+ match get_toolchain_version(dir, &sysroot, Tool::Rustc, &config.extra_env, "rustc ") {
Ok(it) => it,
Err(e) => {
tracing::error!("{e}");
@@ -435,25 +402,24 @@ impl ProjectWorkspace {
}
};
- let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
+ let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(&sysroot));
let data_layout = target_data_layout::get(
- RustcDataLayoutConfig::Rustc(sysroot_ref),
+ RustcDataLayoutConfig::Rustc(&sysroot),
None,
&config.extra_env,
);
let cargo_script =
- CargoWorkspace::fetch_metadata(detached_file, dir, config, sysroot_ref, &|_| ())
- .ok()
- .map(|ws| {
+ CargoWorkspace::fetch_metadata(detached_file, dir, config, &sysroot, &|_| ()).ok().map(
+ |ws| {
(
CargoWorkspace::new(ws, detached_file.clone()),
WorkspaceBuildScripts::default(),
)
- });
+ },
+ );
- let cargo_config_extra_env =
- cargo_config_env(detached_file, &config.extra_env, sysroot_ref);
+ let cargo_config_extra_env = cargo_config_env(detached_file, &config.extra_env, &sysroot);
Ok(ProjectWorkspace {
kind: ProjectWorkspaceKind::DetachedFile {
file: detached_file.to_owned(),
@@ -489,7 +455,7 @@ impl ProjectWorkspace {
cargo,
progress,
self.toolchain.as_ref(),
- self.sysroot.as_ref().ok(),
+ &self.sysroot,
)
.with_context(|| {
format!("Failed to run build scripts for {}", cargo.workspace_root())
@@ -562,17 +528,7 @@ impl ProjectWorkspace {
}
pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
- 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()
- )),
- Err(Some(e)) => Err(anyhow::format_err!(
- "cannot find proc-macro server, the workspace `{}` is missing a sysroot: {e}",
- self.manifest_or_root()
- )),
- }
+ self.sysroot.discover_proc_macro_srv()
}
/// Returns the roots for the current `ProjectWorkspace`
@@ -580,39 +536,37 @@ impl ProjectWorkspace {
/// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> {
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()
- .filter_map(|pkg| {
- if ws[pkg].is_local {
- // the local ones are included in the main `PackageRoot`` below
- return None;
- }
- let pkg_root = ws[pkg].manifest.parent().to_path_buf();
-
- let include = vec![pkg_root.clone()];
-
- let exclude = vec![
- pkg_root.join(".git"),
- pkg_root.join("target"),
- pkg_root.join("tests"),
- pkg_root.join("examples"),
- pkg_root.join("benches"),
- ];
- Some(PackageRoot { is_local: false, include, exclude })
- })
- .collect(),
- SysrootMode::Stitched(_) => vec![],
- };
+ let mut r = match self.sysroot.mode() {
+ SysrootMode::Workspace(ws) => ws
+ .packages()
+ .filter_map(|pkg| {
+ if ws[pkg].is_local {
+ // the local ones are included in the main `PackageRoot`` below
+ return None;
+ }
+ let pkg_root = ws[pkg].manifest.parent().to_path_buf();
+
+ let include = vec![pkg_root.clone()];
+
+ let exclude = vec![
+ pkg_root.join(".git"),
+ pkg_root.join("target"),
+ pkg_root.join("tests"),
+ pkg_root.join("examples"),
+ pkg_root.join("benches"),
+ ];
+ Some(PackageRoot { is_local: false, include, exclude })
+ })
+ .collect(),
+ SysrootMode::Stitched(_) | SysrootMode::Empty => vec![],
+ };
- r.push(PackageRoot {
- is_local: false,
- include: sysroot.src_root().map(|it| it.to_path_buf()).into_iter().collect(),
- exclude: Vec::new(),
- });
- r
- })
+ r.push(PackageRoot {
+ is_local: false,
+ include: self.sysroot.src_root().map(|it| it.to_path_buf()).into_iter().collect(),
+ exclude: Vec::new(),
+ });
+ r
};
match &self.kind {
ProjectWorkspaceKind::Json(project) => project
@@ -731,19 +685,15 @@ impl ProjectWorkspace {
}
pub fn n_packages(&self) -> usize {
+ let sysroot_package_len = self.sysroot.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()
- }
+ ProjectWorkspaceKind::Json(project) => sysroot_package_len + project.n_crates(),
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 = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
cargo.packages().len() + sysroot_package_len + rustc_package_len
}
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())
}
@@ -764,7 +714,7 @@ impl ProjectWorkspace {
rustc_cfg.clone(),
load,
project,
- sysroot.as_ref().ok(),
+ sysroot,
extra_env,
cfg_overrides,
),
@@ -780,7 +730,7 @@ impl ProjectWorkspace {
load,
rustc.as_ref().map(|a| a.as_ref()).ok(),
cargo,
- sysroot.as_ref().ok(),
+ sysroot,
rustc_cfg.clone(),
cfg_overrides,
build_scripts,
@@ -793,7 +743,7 @@ impl ProjectWorkspace {
&mut |path| load(path),
None,
cargo,
- sysroot.as_ref().ok(),
+ sysroot,
rustc_cfg.clone(),
cfg_overrides,
build_scripts,
@@ -803,7 +753,7 @@ impl ProjectWorkspace {
rustc_cfg.clone(),
load,
file,
- sysroot.as_ref().ok(),
+ sysroot,
cfg_overrides,
)
},
@@ -811,9 +761,7 @@ impl ProjectWorkspace {
),
};
- if matches!(sysroot.as_ref().map(|it| it.mode()), Ok(SysrootMode::Stitched(_)))
- && crate_graph.patch_cfg_if()
- {
+ if matches!(sysroot.mode(), SysrootMode::Stitched(_)) && crate_graph.patch_cfg_if() {
tracing::debug!("Patched std to depend on cfg-if")
} else {
tracing::debug!("Did not patch std to depend on cfg-if")
@@ -892,15 +840,14 @@ fn project_json_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
load: FileLoader<'_>,
project: &ProjectJson,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
extra_env: &FxHashMap<String, String>,
override_cfg: &CfgOverrides,
) -> (CrateGraph, ProcMacroPaths) {
let mut res = (CrateGraph::default(), ProcMacroPaths::default());
let (crate_graph, proc_macros) = &mut res;
- let sysroot_deps = sysroot
- .as_ref()
- .map(|sysroot| sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load));
+ let (public_deps, libproc_macro) =
+ sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
let r_a_cfg_flag = CfgFlag::Atom("rust_analyzer".to_owned());
let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
@@ -978,11 +925,9 @@ fn project_json_to_crate_graph(
for (from_idx, krate) in project.crates() {
if let Some(&from) = idx_to_crate_id.get(&from_idx) {
- if let Some((public_deps, libproc_macro)) = &sysroot_deps {
- public_deps.add_to_crate_graph(crate_graph, from);
- if let Some(proc_macro) = libproc_macro {
- add_proc_macro_dep(crate_graph, from, *proc_macro, krate.is_proc_macro);
- }
+ public_deps.add_to_crate_graph(crate_graph, from);
+ if let Some(proc_macro) = libproc_macro {
+ add_proc_macro_dep(crate_graph, from, proc_macro, krate.is_proc_macro);
}
for dep in &krate.deps {
@@ -999,7 +944,7 @@ fn cargo_to_crate_graph(
load: FileLoader<'_>,
rustc: Option<&(CargoWorkspace, WorkspaceBuildScripts)>,
cargo: &CargoWorkspace,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
rustc_cfg: Vec<CfgFlag>,
override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts,
@@ -1008,10 +953,8 @@ fn cargo_to_crate_graph(
let mut res = (CrateGraph::default(), ProcMacroPaths::default());
let crate_graph = &mut res.0;
let proc_macros = &mut res.1;
- let (public_deps, libproc_macro) = match sysroot {
- Some(sysroot) => sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load),
- None => (SysrootPublicDeps::default(), None),
- };
+ let (public_deps, libproc_macro) =
+ sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
let cfg_options = CfgOptions::from_iter(rustc_cfg);
@@ -1188,15 +1131,13 @@ fn detached_file_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
load: FileLoader<'_>,
detached_file: &ManifestPath,
- sysroot: Option<&Sysroot>,
+ sysroot: &Sysroot,
override_cfg: &CfgOverrides,
) -> (CrateGraph, ProcMacroPaths) {
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),
- None => (SysrootPublicDeps::default(), None),
- };
+ let (public_deps, _libproc_macro) =
+ sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load);
let mut cfg_options = CfgOptions::from_iter(rustc_cfg);
cfg_options.insert_atom("test".into());
@@ -1431,7 +1372,7 @@ fn sysroot_to_crate_graph(
load,
None,
cargo,
- None,
+ &Sysroot::empty(),
rustc_cfg,
&CfgOverrides {
global: CfgDiff::new(
@@ -1554,6 +1495,7 @@ fn sysroot_to_crate_graph(
stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
(public_deps, libproc_macro)
}
+ SysrootMode::Empty => (SysrootPublicDeps { deps: vec![] }, None),
}
}
diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs
index 85f964b1dd..e9a4db7a2b 100644
--- a/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -69,11 +69,9 @@ impl Tester {
let cargo_config =
CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
- let sysroot =
- Ok(Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env, false)
- .unwrap());
+ let sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env, false);
let data_layout = target_data_layout::get(
- RustcDataLayoutConfig::Rustc(sysroot.as_ref().ok()),
+ RustcDataLayoutConfig::Rustc(&sysroot),
None,
&cargo_config.extra_env,
);
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 5ee0456c15..41996db32e 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -1783,18 +1783,18 @@ pub(crate) fn handle_open_docs(
let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
ProjectWorkspaceKind::Cargo { cargo, .. }
| ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
- Some((cargo, ws.sysroot.as_ref().ok()))
+ Some((cargo, &ws.sysroot))
}
ProjectWorkspaceKind::Json { .. } => None,
ProjectWorkspaceKind::DetachedFile { .. } => None,
});
let (cargo, sysroot) = match ws_and_sysroot {
- Some((ws, sysroot)) => (Some(ws), sysroot),
+ Some((ws, sysroot)) => (Some(ws), Some(sysroot)),
_ => (None, None),
};
- let sysroot = sysroot.map(|p| p.root().as_str());
+ let sysroot = sysroot.and_then(|p| p.root()).map(|it| it.as_str());
let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_str());
let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs
index 2cf9b53f7c..03bd83aab5 100644
--- a/crates/rust-analyzer/src/lsp/ext.rs
+++ b/crates/rust-analyzer/src/lsp/ext.rs
@@ -500,7 +500,6 @@ pub struct ServerStatusParams {
pub health: Health,
pub quiescent: bool,
pub message: Option<String>,
- pub workspace_info: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index fd14efa1da..627be7e951 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -103,7 +103,6 @@ impl GlobalState {
health: lsp_ext::Health::Ok,
quiescent: self.is_quiescent(),
message: None,
- workspace_info: None,
};
let mut message = String::new();
@@ -164,53 +163,37 @@ impl GlobalState {
let proc_macro_clients =
self.proc_macro_clients.iter().map(Some).chain(iter::repeat_with(|| None));
- let mut workspace_info = "Loaded workspaces:\n".to_owned();
for (ws, proc_macro_client) in self.workspaces.iter().zip(proc_macro_clients) {
- format_to!(workspace_info, "- `{}`\n", ws.manifest_or_root());
- format_to!(workspace_info, " - sysroot:");
-
- match ws.sysroot.as_ref() {
- Err(None) => format_to!(workspace_info, " None"),
- Err(Some(e)) => {
- status.health |= lsp_ext::Health::Warning;
- format_to!(workspace_info, " {e}");
- }
- Ok(s) => {
- format_to!(workspace_info, " `{}`", s.root().to_string());
- if let Some(err) = s
- .check_has_core()
- .err()
- .inspect(|_| status.health |= lsp_ext::Health::Warning)
- {
- format_to!(workspace_info, " ({err})");
- }
- if let Some(src_root) = s.src_root() {
- format_to!(
- workspace_info,
- "\n - sysroot source: `{}`",
- src_root
- );
- }
- format_to!(workspace_info, "\n");
- }
+ if let Some(err) = ws.sysroot.error() {
+ status.health |= lsp_ext::Health::Warning;
+ format_to!(
+ message,
+ "Workspace `{}` has sysroot errors: ",
+ ws.manifest_or_root()
+ );
+ message.push_str(err);
+ message.push_str("\n\n");
}
-
- if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(e)), .. } = &ws.kind {
+ if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(err)), .. } = &ws.kind {
status.health |= lsp_ext::Health::Warning;
- format_to!(workspace_info, " - rustc workspace: {e}\n");
+ format_to!(
+ message,
+ "Failed loading rustc_private crates for workspace `{}`: ",
+ ws.manifest_or_root()
+ );
+ message.push_str(err);
+ message.push_str("\n\n");
};
- if let Some(proc_macro_client) = proc_macro_client {
- format_to!(workspace_info, " - proc-macro server: ");
- match proc_macro_client {
- Ok(it) => format_to!(workspace_info, "`{}`\n", it.path()),
- Err(e) => {
- status.health |= lsp_ext::Health::Warning;
- format_to!(workspace_info, "{e}\n")
- }
- }
+ if let Some(Err(err)) = proc_macro_client {
+ status.health |= lsp_ext::Health::Warning;
+ format_to!(
+ message,
+ "Failed spawning proc-macro server for workspace `{}`: {err}",
+ ws.manifest_or_root()
+ );
+ message.push_str("\n\n");
}
}
- status.workspace_info = Some(workspace_info);
}
if !message.is_empty() {
@@ -534,8 +517,8 @@ impl GlobalState {
.map(|(a, b)| (a.clone(), b.clone()))
.chain(
ws.sysroot
- .as_ref()
- .map(|it| ("RUSTUP_TOOLCHAIN".to_owned(), it.root().to_string())),
+ .root()
+ .map(|it| ("RUSTUP_TOOLCHAIN".to_owned(), it.to_string())),
)
.collect(),
@@ -719,7 +702,7 @@ impl GlobalState {
}
ProjectWorkspaceKind::DetachedFile { .. } => return None,
},
- ws.sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()),
+ ws.sysroot.root().map(ToOwned::to_owned),
))
})
.map(|(id, (root, manifest_path), sysroot_root)| {
diff --git a/crates/rust-analyzer/tests/crate_graph.rs b/crates/rust-analyzer/tests/crate_graph.rs
index 59b229cd06..66481d3d7f 100644
--- a/crates/rust-analyzer/tests/crate_graph.rs
+++ b/crates/rust-analyzer/tests/crate_graph.rs
@@ -21,7 +21,7 @@ fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
rustc: Err(None),
cargo_config_extra_env: Default::default(),
},
- sysroot: Ok(get_fake_sysroot()),
+ sysroot: get_fake_sysroot(),
rustc_cfg: Vec::new(),
cfg_overrides: Default::default(),
toolchain: None,
@@ -69,7 +69,7 @@ fn get_fake_sysroot() -> Sysroot {
// fake sysroot, so we give them both the same path:
let sysroot_dir = AbsPathBuf::assert_utf8(sysroot_path);
let sysroot_src_dir = sysroot_dir.clone();
- Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
+ Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), false)
}
#[test]
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index 5a1397bbb0..d886e405e1 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -1059,11 +1059,11 @@ fn resolve_proc_macro() {
return;
}
- let sysroot = project_model::Sysroot::discover_no_source(
+ let sysroot = project_model::Sysroot::discover(
&AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
&Default::default(),
- )
- .unwrap();
+ false,
+ );
let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap();
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 46c1ccb79b..c8728c33ea 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
<!---
-lsp/ext.rs hash: a39009c351009d16
+lsp/ext.rs hash: 422dcc22c2e56166
If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue:
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index 5b683dccdc..474e18b722 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -472,12 +472,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
if (status.message) {
statusBar.tooltip.appendText(status.message);
}
- if (status.workspaceInfo) {
- if (statusBar.tooltip.value) {
- statusBar.tooltip.appendMarkdown("\n\n---\n\n");
- }
- statusBar.tooltip.appendMarkdown(status.workspaceInfo);
- }
if (statusBar.tooltip.value) {
statusBar.tooltip.appendMarkdown("\n\n---\n\n");
}
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 7d6b16b019..9a7a4aae95 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -241,7 +241,6 @@ export type ServerStatusParams = {
health: "ok" | "warning" | "error";
quiescent: boolean;
message?: string;
- workspaceInfo?: string;
};
export type SsrParams = {
query: string;