Skip to content

Commit c360bf5

Browse files
authored
Merge pull request rust-lang#18788 from Veykril/push-zxystwnotuvq
Remove `rust-analyzer.cargo.sysrootQueryMetadata` config again
2 parents f9a3c41 + 764ce49 commit c360bf5

File tree

12 files changed

+159
-252
lines changed

12 files changed

+159
-252
lines changed

src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use span::Edition;
1515
use toolchain::Tool;
1616

1717
use crate::{CfgOverrides, InvocationStrategy};
18-
use crate::{ManifestPath, Sysroot, SysrootQueryMetadata};
18+
use crate::{ManifestPath, Sysroot};
1919

2020
/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
2121
/// workspace. It pretty closely mirrors `cargo metadata` output.
@@ -89,8 +89,6 @@ pub struct CargoConfig {
8989
pub target: Option<String>,
9090
/// Sysroot loading behavior
9191
pub sysroot: Option<RustLibSource>,
92-
/// How to query metadata for the sysroot crate.
93-
pub sysroot_query_metadata: SysrootQueryMetadata,
9492
pub sysroot_src: Option<AbsPathBuf>,
9593
/// rustc private crate source
9694
pub rustc_source: Option<RustLibSource>,

src/tools/rust-analyzer/crates/project-model/src/lib.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,19 @@ fn parse_cfg(s: &str) -> Result<cfg::CfgAtom, String> {
259259
}
260260

261261
#[derive(Clone, Debug, PartialEq, Eq)]
262-
pub enum SysrootQueryMetadata {
262+
pub enum SysrootSourceWorkspaceConfig {
263263
CargoMetadata(CargoMetadataConfig),
264-
None,
264+
Stitched,
265265
}
266266

267-
impl Default for SysrootQueryMetadata {
267+
impl Default for SysrootSourceWorkspaceConfig {
268268
fn default() -> Self {
269-
SysrootQueryMetadata::CargoMetadata(Default::default())
269+
SysrootSourceWorkspaceConfig::default_cargo()
270+
}
271+
}
272+
273+
impl SysrootSourceWorkspaceConfig {
274+
pub fn default_cargo() -> Self {
275+
SysrootSourceWorkspaceConfig::CargoMetadata(Default::default())
270276
}
271277
}

src/tools/rust-analyzer/crates/project-model/src/sysroot.rs

+86-123
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,37 @@
44
//! but we can't process `.rlib` and need source code instead. The source code
55
//! is typically installed with `rustup component add rust-src` command.
66
7-
use std::{env, fs, ops, path::Path, process::Command};
7+
use std::{
8+
env, fs,
9+
ops::{self, Not},
10+
path::Path,
11+
process::Command,
12+
};
813

914
use anyhow::{format_err, Result};
1015
use base_db::CrateName;
1116
use itertools::Itertools;
1217
use la_arena::{Arena, Idx};
1318
use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
1419
use rustc_hash::FxHashMap;
20+
use stdx::format_to;
1521
use toolchain::{probe_for_binary, Tool};
1622

1723
use crate::{
1824
cargo_workspace::CargoMetadataConfig, utf8_stdout, CargoWorkspace, ManifestPath,
19-
SysrootQueryMetadata,
25+
SysrootSourceWorkspaceConfig,
2026
};
2127

2228
#[derive(Debug, Clone, PartialEq, Eq)]
2329
pub struct Sysroot {
2430
root: Option<AbsPathBuf>,
2531
src_root: Option<AbsPathBuf>,
26-
mode: SysrootMode,
32+
workspace: SysrootWorkspace,
2733
error: Option<String>,
2834
}
2935

3036
#[derive(Debug, Clone, Eq, PartialEq)]
31-
pub(crate) enum SysrootMode {
37+
pub(crate) enum SysrootWorkspace {
3238
Workspace(CargoWorkspace),
3339
Stitched(Stitched),
3440
Empty,
@@ -82,7 +88,7 @@ pub(crate) struct SysrootCrateData {
8288

8389
impl Sysroot {
8490
pub const fn empty() -> Sysroot {
85-
Sysroot { root: None, src_root: None, mode: SysrootMode::Empty, error: None }
91+
Sysroot { root: None, src_root: None, workspace: SysrootWorkspace::Empty, error: None }
8692
}
8793

8894
/// Returns sysroot "root" directory, where `bin/`, `etc/`, `lib/`, `libexec/`
@@ -99,10 +105,10 @@ impl Sysroot {
99105
}
100106

101107
pub fn is_empty(&self) -> bool {
102-
match &self.mode {
103-
SysrootMode::Workspace(ws) => ws.packages().next().is_none(),
104-
SysrootMode::Stitched(stitched) => stitched.crates.is_empty(),
105-
SysrootMode::Empty => true,
108+
match &self.workspace {
109+
SysrootWorkspace::Workspace(ws) => ws.packages().next().is_none(),
110+
SysrootWorkspace::Stitched(stitched) => stitched.crates.is_empty(),
111+
SysrootWorkspace::Empty => true,
106112
}
107113
}
108114

@@ -111,64 +117,51 @@ impl Sysroot {
111117
}
112118

113119
pub fn num_packages(&self) -> usize {
114-
match &self.mode {
115-
SysrootMode::Workspace(ws) => ws.packages().count(),
116-
SysrootMode::Stitched(c) => c.crates().count(),
117-
SysrootMode::Empty => 0,
120+
match &self.workspace {
121+
SysrootWorkspace::Workspace(ws) => ws.packages().count(),
122+
SysrootWorkspace::Stitched(c) => c.crates().count(),
123+
SysrootWorkspace::Empty => 0,
118124
}
119125
}
120126

121-
pub(crate) fn mode(&self) -> &SysrootMode {
122-
&self.mode
127+
pub(crate) fn workspace(&self) -> &SysrootWorkspace {
128+
&self.workspace
123129
}
124130
}
125131

126-
// FIXME: Expose a builder api as loading the sysroot got way too modular and complicated.
127132
impl Sysroot {
128133
/// Attempts to discover the toolchain's sysroot from the given `dir`.
129-
pub fn discover(
130-
dir: &AbsPath,
131-
extra_env: &FxHashMap<String, String>,
132-
sysroot_query_metadata: &SysrootQueryMetadata,
133-
) -> Sysroot {
134+
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Sysroot {
134135
let sysroot_dir = discover_sysroot_dir(dir, extra_env);
135136
let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
136137
discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env)
137138
});
138-
Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, sysroot_query_metadata)
139+
Sysroot::assemble(Some(sysroot_dir), sysroot_src_dir)
139140
}
140141

141142
pub fn discover_with_src_override(
142143
current_dir: &AbsPath,
143144
extra_env: &FxHashMap<String, String>,
144145
sysroot_src_dir: AbsPathBuf,
145-
sysroot_query_metadata: &SysrootQueryMetadata,
146146
) -> Sysroot {
147147
let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
148-
Sysroot::load_core_check(
149-
Some(sysroot_dir),
150-
Some(Ok(sysroot_src_dir)),
151-
sysroot_query_metadata,
152-
)
148+
Sysroot::assemble(Some(sysroot_dir), Some(Ok(sysroot_src_dir)))
153149
}
154150

155-
pub fn discover_sysroot_src_dir(
156-
sysroot_dir: AbsPathBuf,
157-
sysroot_query_metadata: &SysrootQueryMetadata,
158-
) -> Sysroot {
151+
pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot {
159152
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir)
160153
.ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}"));
161-
Sysroot::load_core_check(
162-
Some(Ok(sysroot_dir)),
163-
Some(sysroot_src_dir),
164-
sysroot_query_metadata,
165-
)
154+
Sysroot::assemble(Some(Ok(sysroot_dir)), Some(sysroot_src_dir))
166155
}
167156

168157
pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
169158
get_rustc_src(self.root()?)
170159
}
171160

161+
pub fn new(sysroot_dir: Option<AbsPathBuf>, sysroot_src_dir: Option<AbsPathBuf>) -> Sysroot {
162+
Self::assemble(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok))
163+
}
164+
172165
/// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
173166
pub fn tool(&self, tool: Tool, current_dir: impl AsRef<Path>) -> Command {
174167
match self.root() {
@@ -205,101 +198,59 @@ impl Sysroot {
205198
})
206199
}
207200

208-
pub fn load(
209-
sysroot_dir: Option<AbsPathBuf>,
210-
sysroot_src_dir: Option<AbsPathBuf>,
211-
sysroot_query_metadata: &SysrootQueryMetadata,
212-
) -> Sysroot {
213-
Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), sysroot_query_metadata)
214-
}
215-
216-
fn load_core_check(
217-
sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
218-
sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
219-
sysroot_query_metadata: &SysrootQueryMetadata,
220-
) -> Sysroot {
221-
let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, sysroot_query_metadata);
222-
if sysroot.error.is_none() {
223-
if let Some(src_root) = &sysroot.src_root {
224-
let has_core = match &sysroot.mode {
225-
SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
226-
SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
227-
SysrootMode::Empty => true,
228-
};
229-
if !has_core {
230-
let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
231-
" (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
232-
} else {
233-
", try running `rustup component add rust-src` to possibly fix this"
234-
};
235-
sysroot.error = Some(format!(
236-
"sysroot at `{src_root}` is missing a `core` library{var_note}",
237-
));
238-
}
239-
}
240-
}
241-
sysroot
242-
}
243-
244-
fn load_(
201+
fn assemble(
245202
sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
246203
sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
247-
sysroot_query_metadata: &SysrootQueryMetadata,
248204
) -> Sysroot {
249-
let sysroot_dir = match sysroot_dir {
205+
let mut errors = String::new();
206+
let root = match sysroot_dir {
250207
Some(Ok(sysroot_dir)) => Some(sysroot_dir),
251208
Some(Err(e)) => {
252-
return Sysroot {
253-
root: None,
254-
src_root: None,
255-
mode: SysrootMode::Empty,
256-
error: Some(e.to_string()),
257-
}
209+
format_to!(errors, "{e}\n");
210+
None
258211
}
259212
None => None,
260213
};
261-
let sysroot_src_dir = match sysroot_src_dir {
262-
Some(Ok(sysroot_src_dir)) => sysroot_src_dir,
214+
let src_root = match sysroot_src_dir {
215+
Some(Ok(sysroot_src_dir)) => Some(sysroot_src_dir),
263216
Some(Err(e)) => {
264-
return Sysroot {
265-
root: sysroot_dir,
266-
src_root: None,
267-
mode: SysrootMode::Empty,
268-
error: Some(e.to_string()),
269-
}
270-
}
271-
None => {
272-
return Sysroot {
273-
root: sysroot_dir,
274-
src_root: None,
275-
mode: SysrootMode::Empty,
276-
error: None,
277-
}
217+
format_to!(errors, "{e}\n");
218+
None
278219
}
220+
None => None,
279221
};
280-
if let SysrootQueryMetadata::CargoMetadata(cargo_config) = sysroot_query_metadata {
281-
let library_manifest =
282-
ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap();
222+
Sysroot {
223+
root,
224+
src_root,
225+
workspace: SysrootWorkspace::Empty,
226+
error: errors.is_empty().not().then_some(errors),
227+
}
228+
}
229+
230+
pub fn load_workspace(&mut self, sysroot_source_config: &SysrootSourceWorkspaceConfig) {
231+
assert!(matches!(self.workspace, SysrootWorkspace::Empty), "workspace already loaded");
232+
let Self { root: _, src_root: Some(src_root), workspace, error: _ } = self else { return };
233+
if let SysrootSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config {
234+
let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap();
283235
if fs::metadata(&library_manifest).is_ok() {
284-
if let Some(sysroot) = Self::load_library_via_cargo(
285-
library_manifest,
286-
&sysroot_dir,
287-
&sysroot_src_dir,
288-
cargo_config,
289-
) {
290-
return sysroot;
236+
if let Some(loaded) =
237+
Self::load_library_via_cargo(library_manifest, src_root, cargo_config)
238+
{
239+
*workspace = loaded;
240+
self.load_core_check();
241+
return;
291242
}
292243
}
293244
}
294-
tracing::debug!("Stitching sysroot library: {sysroot_src_dir}");
245+
tracing::debug!("Stitching sysroot library: {src_root}");
295246

296247
let mut stitched = Stitched { crates: Arena::default() };
297248

298249
for path in SYSROOT_CRATES.trim().lines() {
299250
let name = path.split('/').last().unwrap();
300251
let root = [format!("{path}/src/lib.rs"), format!("lib{path}/lib.rs")]
301252
.into_iter()
302-
.map(|it| sysroot_src_dir.join(it))
253+
.map(|it| src_root.join(it))
303254
.filter_map(|it| ManifestPath::try_from(it).ok())
304255
.find(|it| fs::metadata(it).is_ok());
305256

@@ -335,20 +286,37 @@ impl Sysroot {
335286
}
336287
}
337288
}
338-
Sysroot {
339-
root: sysroot_dir,
340-
src_root: Some(sysroot_src_dir),
341-
mode: SysrootMode::Stitched(stitched),
342-
error: None,
289+
*workspace = SysrootWorkspace::Stitched(stitched);
290+
self.load_core_check();
291+
}
292+
293+
fn load_core_check(&mut self) {
294+
if self.error.is_none() {
295+
if let Some(src_root) = &self.src_root {
296+
let has_core = match &self.workspace {
297+
SysrootWorkspace::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
298+
SysrootWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(),
299+
SysrootWorkspace::Empty => true,
300+
};
301+
if !has_core {
302+
let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
303+
" (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
304+
} else {
305+
", try running `rustup component add rust-src` to possibly fix this"
306+
};
307+
self.error = Some(format!(
308+
"sysroot at `{src_root}` is missing a `core` library{var_note}",
309+
));
310+
}
311+
}
343312
}
344313
}
345314

346315
fn load_library_via_cargo(
347316
library_manifest: ManifestPath,
348-
sysroot_dir: &Option<AbsPathBuf>,
349317
sysroot_src_dir: &AbsPathBuf,
350318
cargo_config: &CargoMetadataConfig,
351-
) -> Option<Sysroot> {
319+
) -> Option<SysrootWorkspace> {
352320
tracing::debug!("Loading library metadata: {library_manifest}");
353321
let mut cargo_config = cargo_config.clone();
354322
// the sysroot uses `public-dependency`, so we make cargo think it's a nightly
@@ -423,12 +391,7 @@ impl Sysroot {
423391
});
424392

425393
let cargo_workspace = CargoWorkspace::new(res, library_manifest, Default::default());
426-
Some(Sysroot {
427-
root: sysroot_dir.clone(),
428-
src_root: Some(sysroot_src_dir.clone()),
429-
mode: SysrootMode::Workspace(cargo_workspace),
430-
error: None,
431-
})
394+
Some(SysrootWorkspace::Workspace(cargo_workspace))
432395
}
433396
}
434397

0 commit comments

Comments
 (0)