Skip to content

Commit 3c98b98

Browse files
committed
Re-add rust-analyzer.cargo.sysrootQueryMetadata
1 parent ba56d9b commit 3c98b98

File tree

12 files changed

+150
-51
lines changed

12 files changed

+150
-51
lines changed

crates/project-model/src/cargo_workspace.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use serde_json::from_value;
1313
use span::Edition;
1414
use toolchain::Tool;
1515

16-
use crate::{utf8_stdout, ManifestPath, Sysroot};
16+
use crate::{utf8_stdout, ManifestPath, Sysroot, SysrootQueryMetadata};
1717
use crate::{CfgOverrides, InvocationStrategy};
1818

1919
/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
@@ -85,6 +85,8 @@ pub struct CargoConfig {
8585
pub target: Option<String>,
8686
/// Sysroot loading behavior
8787
pub sysroot: Option<RustLibSource>,
88+
/// How to query metadata for the sysroot crate.
89+
pub sysroot_query_metadata: SysrootQueryMetadata,
8890
pub sysroot_src: Option<AbsPathBuf>,
8991
/// rustc private crate source
9092
pub rustc_source: Option<RustLibSource>,

crates/project-model/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,10 @@ fn parse_cfg(s: &str) -> Result<cfg::CfgAtom, String> {
240240
};
241241
Ok(res)
242242
}
243+
244+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
245+
pub enum SysrootQueryMetadata {
246+
#[default]
247+
CargoMetadata,
248+
None,
249+
}

crates/project-model/src/sysroot.rs

+40-15
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
1414
use rustc_hash::FxHashMap;
1515
use toolchain::{probe_for_binary, Tool};
1616

17-
use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath};
17+
use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, SysrootQueryMetadata};
1818

1919
#[derive(Debug, Clone, PartialEq, Eq)]
2020
pub struct Sysroot {
@@ -123,27 +123,43 @@ impl Sysroot {
123123
// FIXME: Expose a builder api as loading the sysroot got way too modular and complicated.
124124
impl Sysroot {
125125
/// Attempts to discover the toolchain's sysroot from the given `dir`.
126-
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Sysroot {
126+
pub fn discover(
127+
dir: &AbsPath,
128+
extra_env: &FxHashMap<String, String>,
129+
sysroot_query_metadata: SysrootQueryMetadata,
130+
) -> Sysroot {
127131
let sysroot_dir = discover_sysroot_dir(dir, extra_env);
128132
let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
129133
discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env)
130134
});
131-
Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir)
135+
Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, sysroot_query_metadata)
132136
}
133137

134138
pub fn discover_with_src_override(
135139
current_dir: &AbsPath,
136140
extra_env: &FxHashMap<String, String>,
137141
sysroot_src_dir: AbsPathBuf,
142+
sysroot_query_metadata: SysrootQueryMetadata,
138143
) -> Sysroot {
139144
let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
140-
Sysroot::load_core_check(Some(sysroot_dir), Some(Ok(sysroot_src_dir)))
145+
Sysroot::load_core_check(
146+
Some(sysroot_dir),
147+
Some(Ok(sysroot_src_dir)),
148+
sysroot_query_metadata,
149+
)
141150
}
142151

143-
pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot {
152+
pub fn discover_sysroot_src_dir(
153+
sysroot_dir: AbsPathBuf,
154+
sysroot_query_metadata: SysrootQueryMetadata,
155+
) -> Sysroot {
144156
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir)
145157
.ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}"));
146-
Sysroot::load_core_check(Some(Ok(sysroot_dir)), Some(sysroot_src_dir))
158+
Sysroot::load_core_check(
159+
Some(Ok(sysroot_dir)),
160+
Some(sysroot_src_dir),
161+
sysroot_query_metadata,
162+
)
147163
}
148164

149165
pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
@@ -186,15 +202,20 @@ impl Sysroot {
186202
})
187203
}
188204

189-
pub fn load(sysroot_dir: Option<AbsPathBuf>, sysroot_src_dir: Option<AbsPathBuf>) -> Sysroot {
190-
Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok))
205+
pub fn load(
206+
sysroot_dir: Option<AbsPathBuf>,
207+
sysroot_src_dir: Option<AbsPathBuf>,
208+
sysroot_query_metadata: SysrootQueryMetadata,
209+
) -> Sysroot {
210+
Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), sysroot_query_metadata)
191211
}
192212

193213
fn load_core_check(
194214
sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
195215
sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
216+
sysroot_query_metadata: SysrootQueryMetadata,
196217
) -> Sysroot {
197-
let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir);
218+
let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, sysroot_query_metadata);
198219
if sysroot.error.is_none() {
199220
if let Some(src_root) = &sysroot.src_root {
200221
let has_core = match &sysroot.mode {
@@ -220,6 +241,7 @@ impl Sysroot {
220241
fn load_(
221242
sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
222243
sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
244+
sysroot_query_metadata: SysrootQueryMetadata,
223245
) -> Sysroot {
224246
let sysroot_dir = match sysroot_dir {
225247
Some(Ok(sysroot_dir)) => Some(sysroot_dir),
@@ -252,12 +274,15 @@ impl Sysroot {
252274
}
253275
}
254276
};
255-
let library_manifest = ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap();
256-
if fs::metadata(&library_manifest).is_ok() {
257-
if let Some(sysroot) =
258-
Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir)
259-
{
260-
return sysroot;
277+
if sysroot_query_metadata == SysrootQueryMetadata::CargoMetadata {
278+
let library_manifest =
279+
ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap();
280+
if fs::metadata(&library_manifest).is_ok() {
281+
if let Some(sysroot) =
282+
Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir)
283+
{
284+
return sysroot;
285+
}
261286
}
262287
}
263288
tracing::debug!("Stitching sysroot library: {sysroot_src_dir}");

crates/project-model/src/tests.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use triomphe::Arc;
1313

1414
use crate::{
1515
sysroot::SysrootMode, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides,
16-
ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, WorkspaceBuildScripts,
16+
ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, SysrootQueryMetadata,
17+
WorkspaceBuildScripts,
1718
};
1819

1920
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
@@ -116,7 +117,7 @@ fn get_fake_sysroot() -> Sysroot {
116117
// fake sysroot, so we give them both the same path:
117118
let sysroot_dir = AbsPathBuf::assert(sysroot_path);
118119
let sysroot_src_dir = sysroot_dir.clone();
119-
Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir))
120+
Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), SysrootQueryMetadata::CargoMetadata)
120121
}
121122

122123
fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
@@ -231,6 +232,7 @@ fn smoke_test_real_sysroot_cargo() {
231232
let sysroot = Sysroot::discover(
232233
AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
233234
&Default::default(),
235+
SysrootQueryMetadata::CargoMetadata,
234236
);
235237
assert!(matches!(sysroot.mode(), SysrootMode::Workspace(_)));
236238
let project_workspace = ProjectWorkspace {

crates/project-model/src/workspace.rs

+33-28
Original file line numberDiff line numberDiff line change
@@ -211,34 +211,35 @@ impl ProjectWorkspace {
211211
let project_location = project_json.parent().to_path_buf();
212212
let project_json: ProjectJson =
213213
ProjectJson::new(Some(project_json.clone()), &project_location, data);
214-
ProjectWorkspace::load_inline(
215-
project_json,
216-
config.target.as_deref(),
217-
&config.extra_env,
218-
&config.cfg_overrides,
219-
)
214+
ProjectWorkspace::load_inline(project_json, config)
220215
}
221216
ProjectManifest::CargoScript(rust_file) => {
222217
ProjectWorkspace::load_detached_file(rust_file, config)?
223218
}
224219
ProjectManifest::CargoToml(cargo_toml) => {
225220
let sysroot = match (&config.sysroot, &config.sysroot_src) {
226-
(Some(RustLibSource::Discover), None) => {
227-
Sysroot::discover(cargo_toml.parent(), &config.extra_env)
228-
}
221+
(Some(RustLibSource::Discover), None) => Sysroot::discover(
222+
cargo_toml.parent(),
223+
&config.extra_env,
224+
config.sysroot_query_metadata,
225+
),
229226
(Some(RustLibSource::Discover), Some(sysroot_src)) => {
230227
Sysroot::discover_with_src_override(
231228
cargo_toml.parent(),
232229
&config.extra_env,
233230
sysroot_src.clone(),
231+
config.sysroot_query_metadata,
234232
)
235233
}
236-
(Some(RustLibSource::Path(path)), None) => {
237-
Sysroot::discover_sysroot_src_dir(path.clone())
238-
}
239-
(Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => {
240-
Sysroot::load(Some(sysroot.clone()), Some(sysroot_src.clone()))
241-
}
234+
(Some(RustLibSource::Path(path)), None) => Sysroot::discover_sysroot_src_dir(
235+
path.clone(),
236+
config.sysroot_query_metadata,
237+
),
238+
(Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => Sysroot::load(
239+
Some(sysroot.clone()),
240+
Some(sysroot_src.clone()),
241+
config.sysroot_query_metadata,
242+
),
242243
(None, _) => Sysroot::empty(),
243244
};
244245
tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
@@ -352,20 +353,19 @@ impl ProjectWorkspace {
352353
Ok(res)
353354
}
354355

355-
pub fn load_inline(
356-
project_json: ProjectJson,
357-
target: Option<&str>,
358-
extra_env: &FxHashMap<String, String>,
359-
cfg_overrides: &CfgOverrides,
360-
) -> ProjectWorkspace {
361-
let sysroot = Sysroot::load(project_json.sysroot.clone(), project_json.sysroot_src.clone());
356+
pub fn load_inline(project_json: ProjectJson, config: &CargoConfig) -> ProjectWorkspace {
357+
let sysroot = Sysroot::load(
358+
project_json.sysroot.clone(),
359+
project_json.sysroot_src.clone(),
360+
config.sysroot_query_metadata,
361+
);
362362
let cfg_config = RustcCfgConfig::Rustc(&sysroot);
363363
let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot);
364364
let toolchain = match get_toolchain_version(
365365
project_json.path(),
366366
&sysroot,
367367
Tool::Rustc,
368-
extra_env,
368+
&config.extra_env,
369369
"rustc ",
370370
) {
371371
Ok(it) => it,
@@ -375,15 +375,16 @@ impl ProjectWorkspace {
375375
}
376376
};
377377

378-
let rustc_cfg = rustc_cfg::get(target, extra_env, cfg_config);
379-
let data_layout = target_data_layout::get(data_layout_config, target, extra_env);
378+
let target = config.target.as_deref();
379+
let rustc_cfg = rustc_cfg::get(target, &config.extra_env, cfg_config);
380+
let data_layout = target_data_layout::get(data_layout_config, target, &config.extra_env);
380381
ProjectWorkspace {
381382
kind: ProjectWorkspaceKind::Json(project_json),
382383
sysroot,
383384
rustc_cfg,
384385
toolchain,
385386
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
386-
cfg_overrides: cfg_overrides.clone(),
387+
cfg_overrides: config.cfg_overrides.clone(),
387388
}
388389
}
389390

@@ -393,8 +394,12 @@ impl ProjectWorkspace {
393394
) -> anyhow::Result<ProjectWorkspace> {
394395
let dir = detached_file.parent();
395396
let sysroot = match &config.sysroot {
396-
Some(RustLibSource::Path(path)) => Sysroot::discover_sysroot_src_dir(path.clone()),
397-
Some(RustLibSource::Discover) => Sysroot::discover(dir, &config.extra_env),
397+
Some(RustLibSource::Path(path)) => {
398+
Sysroot::discover_sysroot_src_dir(path.clone(), config.sysroot_query_metadata)
399+
}
400+
Some(RustLibSource::Discover) => {
401+
Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
402+
}
398403
None => Sysroot::empty(),
399404
};
400405

crates/rust-analyzer/src/cli/analysis_stats.rs

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ impl flags::AnalysisStats {
6565
true => None,
6666
false => Some(RustLibSource::Discover),
6767
},
68+
sysroot_query_metadata: match self.no_query_sysroot_metadata {
69+
true => project_model::SysrootQueryMetadata::None,
70+
false => project_model::SysrootQueryMetadata::CargoMetadata,
71+
},
6872
all_targets: true,
6973
set_test: !self.no_test,
7074
cfg_overrides: CfgOverrides {

crates/rust-analyzer/src/cli/flags.rs

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ xflags::xflags! {
7171
optional --with-deps
7272
/// Don't load sysroot crates (`std`, `core` & friends).
7373
optional --no-sysroot
74+
/// Don't run cargo metadata on the sysroot to analyze its third-party dependencies.
75+
/// Requires --no-sysroot to not be set.
76+
optional --no-query-sysroot-metadata
7477
/// Don't set #[cfg(test)].
7578
optional --no-test
7679

@@ -235,6 +238,7 @@ pub struct AnalysisStats {
235238
pub only: Option<String>,
236239
pub with_deps: bool,
237240
pub no_sysroot: bool,
241+
pub no_query_sysroot_metadata: bool,
238242
pub no_test: bool,
239243
pub disable_build_scripts: bool,
240244
pub disable_proc_macros: bool,

crates/rust-analyzer/src/cli/rustc_tests.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use profile::StopWatch;
1313
use project_model::target_data_layout::RustcDataLayoutConfig;
1414
use project_model::{
1515
target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind,
16-
RustLibSource, Sysroot,
16+
RustLibSource, Sysroot, SysrootQueryMetadata,
1717
};
1818

1919
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
@@ -74,7 +74,11 @@ impl Tester {
7474
..Default::default()
7575
};
7676

77-
let sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
77+
let sysroot = Sysroot::discover(
78+
tmp_file.parent().unwrap(),
79+
&cargo_config.extra_env,
80+
SysrootQueryMetadata::CargoMetadata,
81+
);
7882
let data_layout = target_data_layout::get(
7983
RustcDataLayoutConfig::Rustc(&sysroot),
8084
None,

crates/rust-analyzer/src/config.rs

+24
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,9 @@ config_data! {
558558
///
559559
/// This option does not take effect until rust-analyzer is restarted.
560560
cargo_sysroot: Option<String> = Some("discover".to_owned()),
561+
/// How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer
562+
/// to analyze third-party dependencies of the standard libraries.
563+
cargo_sysrootQueryMetadata: SysrootQueryMetadata = SysrootQueryMetadata::CargoMetadata,
561564
/// Relative path to the sysroot library sources. If left unset, this will default to
562565
/// `{cargo.sysroot}/lib/rustlib/src/rust/library`.
563566
///
@@ -1868,6 +1871,12 @@ impl Config {
18681871
},
18691872
target: self.cargo_target(source_root).clone(),
18701873
sysroot,
1874+
sysroot_query_metadata: match self.cargo_sysrootQueryMetadata(None) {
1875+
SysrootQueryMetadata::CargoMetadata => {
1876+
project_model::SysrootQueryMetadata::CargoMetadata
1877+
}
1878+
SysrootQueryMetadata::None => project_model::SysrootQueryMetadata::None,
1879+
},
18711880
sysroot_src,
18721881
rustc_source,
18731882
cfg_overrides: project_model::CfgOverrides {
@@ -2559,6 +2568,13 @@ pub enum NumThreads {
25592568
Concrete(usize),
25602569
}
25612570

2571+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
2572+
#[serde(rename_all = "snake_case")]
2573+
pub enum SysrootQueryMetadata {
2574+
CargoMetadata,
2575+
None,
2576+
}
2577+
25622578
macro_rules! _default_val {
25632579
(@verbatim: $s:literal, $ty:ty) => {{
25642580
let default_: $ty = serde_json::from_str(&$s).unwrap();
@@ -3410,6 +3426,14 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
34103426
}
34113427
]
34123428
},
3429+
"SysrootQueryMetadata" => set! {
3430+
"type": "string",
3431+
"enum": ["none", "cargo_metadata"],
3432+
"enumDescriptions": [
3433+
"Do not query sysroot metadata, always use stitched sysroot.",
3434+
"Use `cargo metadata` to query sysroot metadata."
3435+
],
3436+
},
34133437
_ => panic!("missing entry for {ty}: {default} (field {field})"),
34143438
}
34153439

crates/rust-analyzer/src/reload.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,7 @@ impl GlobalState {
316316
LinkedProject::InlineJsonProject(it) => {
317317
let workspace = project_model::ProjectWorkspace::load_inline(
318318
it.clone(),
319-
cargo_config.target.as_deref(),
320-
&cargo_config.extra_env,
321-
&cargo_config.cfg_overrides,
319+
&cargo_config,
322320
);
323321
Ok(workspace)
324322
}

0 commit comments

Comments
 (0)