Skip to content

Commit b915eb3

Browse files
committed
Auto merge of rust-lang#14427 - davidbarsky:davidbarsky/allow-subsequent-workspaces-to-have-proc-macros, r=Veykril
fix: allow new, subsequent `rust-project.json`-based workspaces to get proc macro expansion As detailed in rust-lang/rust-analyzer#14417 (comment), `rust-project.json` workspaces added after the initial `rust-project.json`-based workspace was already indexed by rust-analyzer would not receive procedural macro expansion despite `config.expand_proc_macros` returning true. To fix this issue: 1. I changed `reload.rs` to check which workspaces are newly added. 2. Spawned new procedural macro expansion servers based on the _new_ workspaces. 1. This is to prevent spawning duplicate procedural macro expansion servers for already existing workspaces. While the overall memory usage of duplicate procedural macro servers is minimal, this is more about the _principle_ of not leaking processes 😅. 3. Launched procedural macro expansion if any workspaces are `rust-project.json`-based _or_ `same_workspaces` is true. `same_workspaces` being true (and reachable) indicates that that build scripts have finished building (in Cargo-based projects), while the build scripts in `rust-project.json`-based projects have _already been built_ by the build system that produced the `rust-project.json`. I couldn't really think of structuring this code in a better way without engaging with rust-lang/rust-analyzer#7444.
2 parents ef7756c + 25c59b8 commit b915eb3

File tree

4 files changed

+22
-27
lines changed

4 files changed

+22
-27
lines changed

crates/base-db/src/input.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
1717

1818
// Map from crate id to the name of the crate and path of the proc-macro. If the value is `None`,
1919
// then the crate for the proc-macro hasn't been build yet as the build data is missing.
20-
pub type ProcMacroPaths = FxHashMap<CrateId, Option<(Option<String>, AbsPathBuf)>>;
20+
pub type ProcMacroPaths = FxHashMap<CrateId, Result<(Option<String>, AbsPathBuf), String>>;
2121
pub type ProcMacros = FxHashMap<CrateId, ProcMacroLoadResult>;
2222

2323
/// Files are grouped into source roots. A source root is a directory on the

crates/project-model/src/workspace.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,14 @@ impl ProjectWorkspace {
667667
_ => false,
668668
}
669669
}
670+
671+
/// Returns `true` if the project workspace is [`Json`].
672+
///
673+
/// [`Json`]: ProjectWorkspace::Json
674+
#[must_use]
675+
pub fn is_json(&self) -> bool {
676+
matches!(self, Self::Json { .. })
677+
}
670678
}
671679

672680
fn project_json_to_crate_graph(
@@ -678,7 +686,7 @@ fn project_json_to_crate_graph(
678686
target_layout: TargetLayoutLoadResult,
679687
) -> (CrateGraph, ProcMacroPaths) {
680688
let mut crate_graph = CrateGraph::default();
681-
let mut proc_macros = FxHashMap::default();
689+
let mut proc_macros: ProcMacroPaths = FxHashMap::default();
682690
let sysroot_deps = sysroot.as_ref().map(|sysroot| {
683691
sysroot_to_crate_graph(
684692
&mut crate_graph,
@@ -730,13 +738,11 @@ fn project_json_to_crate_graph(
730738
);
731739
if krate.is_proc_macro {
732740
if let Some(path) = krate.proc_macro_dylib_path.clone() {
733-
proc_macros.insert(
734-
crate_graph_crate_id,
735-
Some((
736-
krate.display_name.as_ref().map(|it| it.canonical_name().to_owned()),
737-
path,
738-
)),
739-
);
741+
let node = Ok((
742+
krate.display_name.as_ref().map(|it| it.canonical_name().to_owned()),
743+
path,
744+
));
745+
proc_macros.insert(crate_graph_crate_id, node);
740746
}
741747
}
742748
(crate_id, crate_graph_crate_id)
@@ -1180,8 +1186,8 @@ fn add_target_crate_root(
11801186
);
11811187
if is_proc_macro {
11821188
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
1183-
Some(it) => it.cloned().map(|path| Some((Some(cargo_name.to_owned()), path))),
1184-
None => Some(None),
1189+
Some(it) => it.cloned().map(|path| Ok((Some(cargo_name.to_owned()), path))),
1190+
None => Some(Err("crate has not yet been build".to_owned())),
11851191
};
11861192
if let Some(proc_macro) = proc_macro {
11871193
proc_macros.insert(crate_id, proc_macro);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub fn load_workspace(
102102
(
103103
crate_id,
104104
path.map_or_else(
105-
|| Err("proc macro crate is missing dylib".to_owned()),
105+
|_| Err("proc macro crate is missing dylib".to_owned()),
106106
|(_, path)| load_proc_macro(proc_macro_server, &path, &[]),
107107
),
108108
)

crates/rust-analyzer/src/reload.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ impl GlobalState {
251251
(
252252
crate_id,
253253
res.map_or_else(
254-
|| Err("proc macro crate is missing dylib".to_owned()),
254+
|_| Err("proc macro crate is missing dylib".to_owned()),
255255
|(crate_name, path)| {
256256
progress(path.display().to_string());
257257
load_proc_macro(
@@ -370,7 +370,7 @@ impl GlobalState {
370370
let files_config = self.config.files();
371371
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
372372

373-
if self.proc_macro_clients.is_empty() {
373+
if self.proc_macro_clients.is_empty() || !same_workspaces {
374374
if let Some((path, path_manually_set)) = self.config.proc_macro_srv() {
375375
tracing::info!("Spawning proc-macro servers");
376376
self.proc_macro_clients = self
@@ -448,19 +448,8 @@ impl GlobalState {
448448
};
449449
let mut change = Change::new();
450450

451-
if same_workspaces {
452-
if self.config.expand_proc_macros() {
453-
self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
454-
}
455-
} else {
456-
// Set up errors for proc-macros upfront that we haven't run build scripts yet
457-
let mut proc_macros = FxHashMap::default();
458-
for paths in proc_macro_paths {
459-
proc_macros.extend(paths.into_iter().map(move |(crate_id, _)| {
460-
(crate_id, Err("crate has not yet been build".to_owned()))
461-
}));
462-
}
463-
change.set_proc_macros(proc_macros);
451+
if self.config.expand_proc_macros() {
452+
self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
464453
}
465454
change.set_crate_graph(crate_graph);
466455
self.analysis_host.apply_change(change);

0 commit comments

Comments
 (0)