Auto merge of #17287 - Veykril:sysroot-encode-empty, r=Veykril

Allow sysroots to only consist of the source root dir

Fixes https://github.com/rust-lang/rust-analyzer/issues/17159

This PR encodes the `None` case of an optional sysroot into `Sysroot` itself. This simplifies a lot of things and allows us to have sysroots that consist of nothing, only standard library sources, everything but the standard library sources or everything. This makes things a lot more flexible. Additionally, this removes the workspace status bar info again, as it turns out that that can be too much information for the status bar to handle (this is better rendered somewhere else, like in the status view).
This commit is contained in:
bors 2024-05-23 18:13:47 +00:00
commit f6fc109fcb
18 changed files with 277 additions and 361 deletions

View file

@ -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(),
)

View file

@ -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)

View file

@ -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())

View file

@ -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())

View file

@ -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 {

View file

@ -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_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 discover_rustc_src(&self) -> Option<ManifestPath> {
get_rustc_src(&self.root)
}
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))
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,
}
}
}

View file

@ -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([

View file

@ -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 {

View file

@ -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,
)
.map_err(|e| {
Some(format!("Failed to find sysroot for {dir}. Is rust-src installed? {e}"))
}),
None => Err(None),
Some(RustLibSource::Discover) => {
Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
}
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 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 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 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),
}
}

View file

@ -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,
);

View file

@ -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 {

View file

@ -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)]

View file

@ -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 ProjectWorkspaceKind::Cargo { rustc: Err(Some(e)), .. } = &ws.kind {
if let Some(err) = ws.sysroot.error() {
status.health |= lsp_ext::Health::Warning;
format_to!(workspace_info, " - rustc workspace: {e}\n");
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(err)), .. } = &ws.kind {
status.health |= lsp_ext::Health::Warning;
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)| {

View file

@ -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]

View file

@ -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();

View file

@ -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:

View file

@ -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");
}

View file

@ -241,7 +241,6 @@ export type ServerStatusParams = {
health: "ok" | "warning" | "error";
quiescent: boolean;
message?: string;
workspaceInfo?: string;
};
export type SsrParams = {
query: string;