Skip to content

Commit ac86b8e

Browse files
committed
Auto merge of #12856 - Veykril:multi-proc-srv, r=Veykril
feat: Spawn a proc-macro-srv instance per workspace cc #12855 The idea is to have each server be spawned with the appropriate toolchain, that way workspaces with differing toolchains shouldn't suffer from proc-macro abi mismatches.
2 parents c7788ad + 50b27e5 commit ac86b8e

File tree

4 files changed

+31
-28
lines changed

4 files changed

+31
-28
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ pub fn load_workspace(
6060

6161
let proc_macro_client = if load_config.with_proc_macro {
6262
let path = AbsPathBuf::assert(std::env::current_exe()?);
63-
Some(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
63+
Ok(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
6464
} else {
65-
None
65+
Err("proc macro server not started".to_owned())
6666
};
6767

6868
let crate_graph = ws.to_crate_graph(
@@ -89,7 +89,7 @@ pub fn load_workspace(
8989
if load_config.prefill_caches {
9090
host.analysis().parallel_prime_caches(1, |_| {})?;
9191
}
92-
Ok((host, vfs, proc_macro_client))
92+
Ok((host, vfs, proc_macro_client.ok()))
9393
}
9494

9595
fn load_crate_graph(

crates/rust-analyzer/src/global_state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub(crate) struct GlobalState {
6161
pub(crate) proc_macro_changed: bool,
6262
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
6363
pub(crate) source_root_config: SourceRootConfig,
64-
pub(crate) proc_macro_client: Option<ProcMacroServer>,
64+
pub(crate) proc_macro_clients: Vec<Result<ProcMacroServer, String>>,
6565

6666
pub(crate) flycheck: Vec<FlycheckHandle>,
6767
pub(crate) flycheck_sender: Sender<flycheck::Message>,
@@ -151,7 +151,7 @@ impl GlobalState {
151151
proc_macro_changed: false,
152152
last_reported_status: None,
153153
source_root_config: SourceRootConfig::default(),
154-
proc_macro_client: None,
154+
proc_macro_clients: vec![],
155155

156156
flycheck: Vec::new(),
157157
flycheck_sender,

crates/rust-analyzer/src/handlers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::{
4444
};
4545

4646
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<()> {
47-
state.proc_macro_client = None;
47+
state.proc_macro_clients.clear();
4848
state.proc_macro_changed = false;
4949
state.fetch_workspaces_queue.request_op("reload workspace request".to_string());
5050
state.fetch_build_data_queue.request_op("reload workspace request".to_string());

crates/rust-analyzer/src/reload.rs

+25-22
Original file line numberDiff line numberDiff line change
@@ -303,18 +303,21 @@ impl GlobalState {
303303
let files_config = self.config.files();
304304
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
305305

306-
if self.proc_macro_client.is_none() {
306+
if self.proc_macro_clients.is_empty() {
307307
if let Some((path, args)) = self.config.proc_macro_srv() {
308-
match ProcMacroServer::spawn(path.clone(), args) {
309-
Ok(it) => self.proc_macro_client = Some(it),
310-
Err(err) => {
311-
tracing::error!(
312-
"Failed to run proc_macro_srv from path {}, error: {:?}",
313-
path.display(),
314-
err
315-
);
316-
}
317-
}
308+
self.proc_macro_clients = (0..self.workspaces.len())
309+
.map(|_| {
310+
ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
311+
let error = format!(
312+
"Failed to run proc_macro_srv from path {}, error: {:?}",
313+
path.display(),
314+
err
315+
);
316+
tracing::error!(error);
317+
error
318+
})
319+
})
320+
.collect();
318321
}
319322
}
320323

@@ -331,15 +334,7 @@ impl GlobalState {
331334

332335
// Create crate graph from all the workspaces
333336
let crate_graph = {
334-
let proc_macro_client = self.proc_macro_client.as_ref();
335337
let dummy_replacements = self.config.dummy_replacements();
336-
let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
337-
load_proc_macro(
338-
proc_macro_client,
339-
path,
340-
dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
341-
)
342-
};
343338

344339
let vfs = &mut self.vfs.write().0;
345340
let loader = &mut self.loader;
@@ -359,7 +354,15 @@ impl GlobalState {
359354
};
360355

361356
let mut crate_graph = CrateGraph::default();
362-
for ws in self.workspaces.iter() {
357+
for (idx, ws) in self.workspaces.iter().enumerate() {
358+
let proc_macro_client = self.proc_macro_clients[idx].as_ref();
359+
let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
360+
load_proc_macro(
361+
proc_macro_client,
362+
path,
363+
dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
364+
)
365+
};
363366
crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
364367
}
365368
crate_graph
@@ -536,14 +539,14 @@ impl SourceRootConfig {
536539
/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
537540
/// with an identity dummy expander.
538541
pub(crate) fn load_proc_macro(
539-
server: Option<&ProcMacroServer>,
542+
server: Result<&ProcMacroServer, &String>,
540543
path: &AbsPath,
541544
dummy_replace: &[Box<str>],
542545
) -> ProcMacroLoadResult {
543546
let res: Result<Vec<_>, String> = (|| {
544547
let dylib = MacroDylib::new(path.to_path_buf())
545548
.map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
546-
let server = server.ok_or_else(|| format!("Proc-macro server not started"))?;
549+
let server = server.map_err(ToOwned::to_owned)?;
547550
let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
548551
if vec.is_empty() {
549552
return Err("proc macro library returned no proc macros".to_string());

0 commit comments

Comments
 (0)