diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index 6c1eccb75e631..392bda51b528d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs index 8e1f7fdcded7c..d2f423590e2c4 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 @@ -65,7 +65,7 @@ impl WorkspaceBuildScripts { allowed_features: &FxHashSet, manifest_path: &ManifestPath, toolchain: Option<&Version>, - sysroot: Option<&Sysroot>, + sysroot: &Sysroot, ) -> io::Result { 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 { 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, - 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/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 9955f2687c917..632ba1cacf213 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 @@ -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 { 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 { 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, - sysroot: Option<&Sysroot>, + sysroot: &Sysroot, ) -> Option { - 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, - sysroot: Option<&Sysroot>, + sysroot: &Sysroot, ) -> Vec { - 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/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs index 5520cdaff6b00..88fb10a68c617 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/env.rs +++ b/src/tools/rust-analyzer/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, - sysroot: Option<&Sysroot>, + sysroot: &Sysroot, ) -> FxHashMap { - 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/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs index 4f69b2b96f0c0..26499308ce96c 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs +++ b/src/tools/rust-analyzer/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 { 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/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index e6bbe6ede8a0e..653e7157bcb3c 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/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>>, + root: Option, + src_root: Option, 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, } #[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 { - 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, metadata: bool, - ) -> Result { - 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, - ) -> Result { - 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, - src: AbsPathBuf, + sysroot_src_dir: AbsPathBuf, metadata: bool, - ) -> Result { - 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 { - 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 { - 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 { + 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::::as_ref(&sysroot.root)); + cmd.env("RUSTUP_TOOLCHAIN", AsRef::::as_ref(root)); cmd } _ => Command::new(tool.path()), @@ -232,35 +178,89 @@ impl Sysroot { } pub fn discover_proc_macro_srv(&self) -> anyhow::Result { + 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, + sysroot_src_dir: Option, + metadata: bool, + ) -> Sysroot { + Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), metadata) + } + + fn load_core_check( + sysroot_dir: Option>, + sysroot_src_dir: Option>, + 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>, sysroot_src_dir: Option>, 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, ¤t_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/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs index 4e810a0232ea9..8a8a2d32558b3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 3d5a934fc92e7..a6730863d6b2d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 85621444e3395..0d2174073a2a9 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/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>, + 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, 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, 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 { - 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 { 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, load: FileLoader<'_>, project: &ProjectJson, - sysroot: Option<&Sysroot>, + sysroot: &Sysroot, extra_env: &FxHashMap, 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> = 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, 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, 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/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 85f964b1dd931..e9a4db7a2b0dd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 5ee0456c15df8..41996db32ea94 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 2cf9b53f7c8d2..03bd83aab5f52 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -500,7 +500,6 @@ pub struct ServerStatusParams { pub health: Health, pub quiescent: bool, pub message: Option, - pub workspace_info: Option, } #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index fd14efa1da568..627be7e951adc 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs index 59b229cd06454..66481d3d7f5e1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 5a1397bbb0e77..d886e405e14ea 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 46c1ccb79bf9b..c8728c33ea096 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@