Skip to content

Commit b5dfdf5

Browse files
committed
Use build scripts from rustc source workspace
1 parent c7c582a commit b5dfdf5

File tree

7 files changed

+135
-68
lines changed

7 files changed

+135
-68
lines changed

crates/load-cargo/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub fn load_workspace_at(
4040
) -> anyhow::Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroServer>)> {
4141
let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
4242
let root = ProjectManifest::discover_single(&root)?;
43-
let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
43+
let mut workspace = ProjectWorkspace::load(root, cargo_config, progress, false)?;
4444

4545
if load_config.load_out_dirs_from_check {
4646
let build_scripts = workspace.run_build_scripts(cargo_config, progress)?;
@@ -81,6 +81,7 @@ pub fn load_workspace(
8181
vfs.file_id(&path)
8282
},
8383
extra_env,
84+
None,
8485
);
8586
let proc_macros = {
8687
let proc_macro_server = match &proc_macro_server {

crates/project-model/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub use crate::{
5050
manifest_path::ManifestPath,
5151
project_json::{ProjectJson, ProjectJsonData},
5252
sysroot::Sysroot,
53-
workspace::{CfgOverrides, PackageRoot, ProjectWorkspace},
53+
workspace::{CfgOverrides, PackageRoot, ProjectWorkspace, RustcWorkspace},
5454
};
5555

5656
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]

crates/project-model/src/tests.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use rustc_hash::FxHashMap;
1111
use serde::de::DeserializeOwned;
1212

1313
use crate::{
14-
CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
15-
WorkspaceBuildScripts,
14+
CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, RustcWorkspace,
15+
Sysroot, WorkspaceBuildScripts,
1616
};
1717

1818
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
@@ -29,7 +29,7 @@ fn load_cargo_with_overrides(
2929
cargo: cargo_workspace,
3030
build_scripts: WorkspaceBuildScripts::default(),
3131
sysroot: Err(None),
32-
rustc: Err(None),
32+
rustc: RustcWorkspace::Loaded(Err(None)),
3333
rustc_cfg: Vec::new(),
3434
cfg_overrides,
3535
toolchain: None,
@@ -48,7 +48,7 @@ fn load_cargo_with_sysroot(
4848
cargo: cargo_workspace,
4949
build_scripts: WorkspaceBuildScripts::default(),
5050
sysroot: Ok(get_fake_sysroot()),
51-
rustc: Err(None),
51+
rustc: RustcWorkspace::Loaded(Err(None)),
5252
rustc_cfg: Vec::new(),
5353
cfg_overrides: Default::default(),
5454
toolchain: None,
@@ -62,6 +62,7 @@ fn load_cargo_with_sysroot(
6262
}
6363
},
6464
&Default::default(),
65+
None,
6566
)
6667
}
6768

@@ -146,6 +147,7 @@ fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacro
146147
}
147148
},
148149
&Default::default(),
150+
None,
149151
)
150152
}
151153

crates/project-model/src/workspace.rs

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use crate::{
2323
project_json::Crate,
2424
rustc_cfg::{self, RustcCfgConfig},
2525
sysroot::SysrootCrate,
26-
target_data_layout, utf8_stdout, CargoConfig, CargoWorkspace, InvocationStrategy, ManifestPath,
27-
Package, ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
26+
target_data_layout, utf8_stdout, CargoConfig, CargoWorkspace, InvocationStrategy, Package,
27+
ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
2828
};
2929

3030
/// A set of cfg-overrides per crate.
@@ -53,14 +53,34 @@ pub struct PackageRoot {
5353
pub exclude: Vec<AbsPathBuf>,
5454
}
5555

56+
#[derive(Clone, PartialEq)]
57+
pub enum RustcWorkspace {
58+
/// A globally-configured rustc source location is being opened as a rust-analyzer workspace
59+
Opening,
60+
/// The rustc source is loaded, e.g. from sysroot, but is not a rust-analyzer workspace
61+
Loaded(Result<(CargoWorkspace, WorkspaceBuildScripts), Option<String>>),
62+
}
63+
64+
impl RustcWorkspace {
65+
/// Returns the loaded `CargoWorkspace` of the rustc source.
66+
/// Will be `None` if either the rustc source is opened as a rust-analyzer workspace
67+
/// or its loading failed.
68+
fn loaded(&self) -> Option<&(CargoWorkspace, WorkspaceBuildScripts)> {
69+
match self {
70+
Self::Opening => None,
71+
Self::Loaded(res) => res.as_ref().ok(),
72+
}
73+
}
74+
}
75+
5676
#[derive(Clone)]
5777
pub enum ProjectWorkspace {
5878
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
5979
Cargo {
6080
cargo: CargoWorkspace,
6181
build_scripts: WorkspaceBuildScripts,
6282
sysroot: Result<Sysroot, Option<String>>,
63-
rustc: Result<(CargoWorkspace, WorkspaceBuildScripts), Option<String>>,
83+
rustc: RustcWorkspace,
6484
/// Holds cfg flags for the current target. We get those by running
6585
/// `rustc --print cfg`.
6686
///
@@ -119,7 +139,7 @@ impl fmt::Debug for ProjectWorkspace {
119139
.field("sysroot", &sysroot.is_ok())
120140
.field(
121141
"n_rustc_compiler_crates",
122-
&rustc.as_ref().map_or(0, |(rc, _)| rc.packages().len()),
142+
&rustc.loaded().map_or(0, |(rc, _)| rc.packages().len()),
123143
)
124144
.field("n_rustc_cfg", &rustc_cfg.len())
125145
.field("n_cfg_overrides", &cfg_overrides.len())
@@ -151,15 +171,17 @@ impl ProjectWorkspace {
151171
manifest: ProjectManifest,
152172
config: &CargoConfig,
153173
progress: &dyn Fn(String),
174+
opening_rustc_workspace: bool,
154175
) -> anyhow::Result<ProjectWorkspace> {
155-
ProjectWorkspace::load_inner(&manifest, config, progress)
176+
ProjectWorkspace::load_inner(&manifest, config, progress, opening_rustc_workspace)
156177
.with_context(|| format!("Failed to load the project at {manifest}"))
157178
}
158179

159180
fn load_inner(
160181
manifest: &ProjectManifest,
161182
config: &CargoConfig,
162183
progress: &dyn Fn(String),
184+
opening_rustc_workspace: bool,
163185
) -> anyhow::Result<ProjectWorkspace> {
164186
let version = |current_dir, cmd_path, prefix: &str| {
165187
let cargo_version = utf8_stdout({
@@ -236,48 +258,56 @@ impl ProjectWorkspace {
236258
tracing::info!(workspace = %cargo_toml, src_root = %sysroot.src_root(), root = %sysroot.root(), "Using sysroot");
237259
}
238260

239-
let rustc_dir = match &config.rustc_source {
240-
Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
241-
.map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
242-
Some(RustLibSource::Discover) => {
243-
sysroot.as_ref().ok().and_then(Sysroot::discover_rustc_src).ok_or_else(
244-
|| Some(format!("Failed to discover rustc source for sysroot.")),
245-
)
246-
}
247-
None => Err(None),
248-
};
249-
250-
let rustc = rustc_dir.and_then(|rustc_dir| {
251-
tracing::info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
252-
match CargoWorkspace::fetch_metadata(
253-
&rustc_dir,
254-
cargo_toml.parent(),
255-
&CargoConfig {
256-
features: crate::CargoFeatures::default(),
257-
..config.clone()
258-
},
259-
progress,
260-
) {
261-
Ok(meta) => {
262-
let workspace = CargoWorkspace::new(meta);
263-
let buildscripts = WorkspaceBuildScripts::rustc_crates(
264-
&workspace,
265-
cargo_toml.parent(),
266-
&config.extra_env,
267-
);
268-
Ok((workspace, buildscripts))
261+
let rustc = if opening_rustc_workspace {
262+
RustcWorkspace::Opening
263+
} else {
264+
let rustc_dir = match &config.rustc_source {
265+
// `config.rustc_source == Some(Path(...))` while `!opening_rustc_workspace` should only occur if
266+
// `ManifestPath::try_from(rustc_dir)` failed in `fetch_workspaces`, so no need to attempt it here
267+
// again.
268+
Some(RustLibSource::Path(path)) => {
269+
Err(Some(format!("rustc source path is not absolute: {path}")))
269270
}
270-
Err(e) => {
271-
tracing::error!(
272-
%e,
273-
"Failed to read Cargo metadata from rustc source at {rustc_dir}",
274-
);
275-
Err(Some(format!(
276-
"Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
277-
)))
271+
Some(RustLibSource::Discover) => {
272+
sysroot.as_ref().ok().and_then(Sysroot::discover_rustc_src).ok_or_else(
273+
|| Some(format!("Failed to discover rustc source for sysroot.")),
274+
)
278275
}
279-
}
280-
});
276+
None => Err(None),
277+
};
278+
279+
RustcWorkspace::Loaded(rustc_dir.and_then(|rustc_dir| {
280+
tracing::info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
281+
match CargoWorkspace::fetch_metadata(
282+
&rustc_dir,
283+
cargo_toml.parent(),
284+
&CargoConfig {
285+
features: crate::CargoFeatures::default(),
286+
..config.clone()
287+
},
288+
progress,
289+
) {
290+
Ok(meta) => {
291+
let workspace = CargoWorkspace::new(meta);
292+
let buildscripts = WorkspaceBuildScripts::rustc_crates(
293+
&workspace,
294+
cargo_toml.parent(),
295+
&config.extra_env,
296+
);
297+
Ok((workspace, buildscripts))
298+
}
299+
Err(e) => {
300+
tracing::error!(
301+
%e,
302+
"Failed to read Cargo metadata from rustc source at {rustc_dir}",
303+
);
304+
Err(Some(format!(
305+
"Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
306+
)))
307+
}
308+
}
309+
}))
310+
};
281311

282312
let rustc_cfg = rustc_cfg::get(
283313
config.target.as_deref(),
@@ -564,7 +594,7 @@ impl ProjectWorkspace {
564594
PackageRoot { is_local, include, exclude }
565595
})
566596
.chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root())))
567-
.chain(rustc.iter().flat_map(|(rustc, _)| {
597+
.chain(rustc.loaded().iter().flat_map(|(rustc, _)| {
568598
rustc.packages().map(move |krate| PackageRoot {
569599
is_local: false,
570600
include: vec![rustc[krate].manifest.parent().to_path_buf()],
@@ -592,7 +622,7 @@ impl ProjectWorkspace {
592622
sysroot_package_len + project.n_crates()
593623
}
594624
ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => {
595-
let rustc_package_len = rustc.as_ref().map_or(0, |(it, _)| it.packages().len());
625+
let rustc_package_len = rustc.loaded().map_or(0, |(it, _)| it.packages().len());
596626
let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.crates().len());
597627
cargo.packages().len() + sysroot_package_len + rustc_package_len
598628
}
@@ -607,6 +637,7 @@ impl ProjectWorkspace {
607637
&self,
608638
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
609639
extra_env: &FxHashMap<String, String>,
640+
opened_rustc_workspace: Option<(&CargoWorkspace, &WorkspaceBuildScripts)>,
610641
) -> (CrateGraph, ProcMacroPaths) {
611642
let _p = profile::span("ProjectWorkspace::to_crate_graph");
612643

@@ -633,7 +664,10 @@ impl ProjectWorkspace {
633664
target_layout,
634665
} => cargo_to_crate_graph(
635666
load,
636-
rustc.as_ref().ok(),
667+
match rustc {
668+
RustcWorkspace::Opening => opened_rustc_workspace,
669+
RustcWorkspace::Loaded(res) => res.as_ref().ok().map(|(a, b)| (a, b)),
670+
},
637671
cargo,
638672
sysroot.as_ref().ok(),
639673
rustc_cfg.clone(),
@@ -844,7 +878,7 @@ fn project_json_to_crate_graph(
844878

845879
fn cargo_to_crate_graph(
846880
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
847-
rustc: Option<&(CargoWorkspace, WorkspaceBuildScripts)>,
881+
rustc: Option<(&CargoWorkspace, &WorkspaceBuildScripts)>,
848882
cargo: &CargoWorkspace,
849883
sysroot: Option<&Sysroot>,
850884
rustc_cfg: Vec<CfgFlag>,
@@ -1030,13 +1064,7 @@ fn cargo_to_crate_graph(
10301064
&pkg_crates,
10311065
&cfg_options,
10321066
override_cfg,
1033-
if rustc_workspace.workspace_root() == cargo.workspace_root() {
1034-
// the rustc workspace does not use the installed toolchain's proc-macro server
1035-
// so we need to make sure we don't use the pre compiled proc-macros there either
1036-
build_scripts
1037-
} else {
1038-
rustc_build_scripts
1039-
},
1067+
rustc_build_scripts,
10401068
target_layout,
10411069
channel,
10421070
);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl flags::AnalysisStats {
7070
let path = AbsPathBuf::assert(env::current_dir()?.join(&self.path));
7171
let manifest = ProjectManifest::discover_single(&path)?;
7272

73-
let mut workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
73+
let mut workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress, false)?;
7474
let metadata_time = db_load_sw.elapsed();
7575
let load_cargo_config = LoadCargoConfig {
7676
load_out_dirs_from_check: !self.disable_build_scripts,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl flags::Lsif {
299299
let path = AbsPathBuf::assert(env::current_dir()?.join(&self.path));
300300
let manifest = ProjectManifest::discover_single(&path)?;
301301

302-
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
302+
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress, false)?;
303303

304304
let (host, vfs, _proc_macro) =
305305
load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?;

0 commit comments

Comments
 (0)