Skip to content

Commit 71ddf07

Browse files
authored
Merge pull request #21139 from Veykril/push-wmxmrovmrrxx
internal: Gate spawning proc-macro-srv with --format on toolchain version
2 parents 3a0d3d5 + 0bc8802 commit 71ddf07

File tree

6 files changed

+89
-56
lines changed

6 files changed

+89
-56
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/load-cargo/src/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,13 @@ pub fn load_workspace_into_db(
9696
tracing::debug!(?load_config, "LoadCargoConfig");
9797
let proc_macro_server = match &load_config.with_proc_macro_server {
9898
ProcMacroServerChoice::Sysroot => ws.find_sysroot_proc_macro_srv().map(|it| {
99-
it.and_then(|it| ProcMacroClient::spawn(&it, extra_env).map_err(Into::into)).map_err(
100-
|e| ProcMacroLoadingError::ProcMacroSrvError(e.to_string().into_boxed_str()),
101-
)
99+
it.and_then(|it| {
100+
ProcMacroClient::spawn(&it, extra_env, ws.toolchain.as_ref()).map_err(Into::into)
101+
})
102+
.map_err(|e| ProcMacroLoadingError::ProcMacroSrvError(e.to_string().into_boxed_str()))
102103
}),
103104
ProcMacroServerChoice::Explicit(path) => {
104-
Some(ProcMacroClient::spawn(path, extra_env).map_err(|e| {
105+
Some(ProcMacroClient::spawn(path, extra_env, ws.toolchain.as_ref()).map_err(|e| {
105106
ProcMacroLoadingError::ProcMacroSrvError(e.to_string().into_boxed_str())
106107
}))
107108
}

crates/proc-macro-api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ span = { path = "../span", version = "0.0.0", default-features = false}
3030

3131
intern.workspace = true
3232
postcard.workspace = true
33+
semver.workspace = true
3334

3435
[features]
3536
sysroot-abi = ["proc-macro-srv", "proc-macro-srv/sysroot-abi"]

crates/proc-macro-api/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mod legacy_protocol;
1818
mod process;
1919

2020
use paths::{AbsPath, AbsPathBuf};
21+
use semver::Version;
2122
use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span};
2223
use std::{fmt, io, sync::Arc, time::SystemTime};
2324

@@ -125,8 +126,9 @@ impl ProcMacroClient {
125126
env: impl IntoIterator<
126127
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
127128
> + Clone,
129+
version: Option<&Version>,
128130
) -> io::Result<ProcMacroClient> {
129-
let process = ProcMacroServerProcess::run(process_path, env)?;
131+
let process = ProcMacroServerProcess::run(process_path, env, version)?;
130132
Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() })
131133
}
132134

crates/proc-macro-api/src/process.rs

Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{
88
};
99

1010
use paths::AbsPath;
11+
use semver::Version;
1112
use stdx::JodChild;
1213

1314
use crate::{
@@ -30,13 +31,8 @@ pub(crate) struct ProcMacroServerProcess {
3031

3132
#[derive(Debug, Clone)]
3233
pub(crate) enum Protocol {
33-
LegacyJson {
34-
mode: SpanMode,
35-
},
36-
#[expect(dead_code)]
37-
Postcard {
38-
mode: SpanMode,
39-
},
34+
LegacyJson { mode: SpanMode },
35+
LegacyPostcard { mode: SpanMode },
4036
}
4137

4238
/// Maintains the state of the proc-macro server process.
@@ -54,50 +50,76 @@ impl ProcMacroServerProcess {
5450
env: impl IntoIterator<
5551
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
5652
> + Clone,
53+
version: Option<&Version>,
5754
) -> io::Result<ProcMacroServerProcess> {
58-
let create_srv = || {
59-
let mut process = Process::run(process_path, env.clone())?;
60-
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
55+
const VERSION: Version = Version::new(1, 93, 0);
56+
// we do `>` for nightly as this started working in the middle of the 1.93 nightly release, so we dont want to break on half of the nightlies
57+
let has_working_format_flag = version.map_or(false, |v| {
58+
if v.pre.as_str() == "nightly" { *v > VERSION } else { *v >= VERSION }
59+
});
6160

62-
io::Result::Ok(ProcMacroServerProcess {
63-
state: Mutex::new(ProcessSrvState { process, stdin, stdout }),
64-
version: 0,
65-
protocol: Protocol::LegacyJson { mode: SpanMode::Id },
66-
exited: OnceLock::new(),
67-
})
61+
let formats: &[_] = if has_working_format_flag {
62+
&[
63+
(Some("postcard-legacy"), Protocol::LegacyPostcard { mode: SpanMode::Id }),
64+
(Some("json-legacy"), Protocol::LegacyJson { mode: SpanMode::Id }),
65+
]
66+
} else {
67+
&[(None, Protocol::LegacyJson { mode: SpanMode::Id })]
6868
};
69-
let mut srv = create_srv()?;
70-
tracing::info!("sending proc-macro server version check");
71-
match srv.version_check() {
72-
Ok(v) if v > version::CURRENT_API_VERSION => {
73-
#[allow(clippy::disallowed_methods)]
74-
let process_version = Command::new(process_path)
75-
.arg("--version")
76-
.output()
77-
.map(|output| String::from_utf8_lossy(&output.stdout).trim().to_owned())
78-
.unwrap_or_else(|_| "unknown version".to_owned());
79-
Err(io::Error::other(format!(
80-
"Your installed proc-macro server is too new for your rust-analyzer. API version: {}, server version: {process_version}. \
69+
70+
let mut err = None;
71+
for &(format, ref protocol) in formats {
72+
let create_srv = || {
73+
let mut process = Process::run(process_path, env.clone(), format)?;
74+
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
75+
76+
io::Result::Ok(ProcMacroServerProcess {
77+
state: Mutex::new(ProcessSrvState { process, stdin, stdout }),
78+
version: 0,
79+
protocol: protocol.clone(),
80+
exited: OnceLock::new(),
81+
})
82+
};
83+
let mut srv = create_srv()?;
84+
tracing::info!("sending proc-macro server version check");
85+
match srv.version_check() {
86+
Ok(v) if v > version::CURRENT_API_VERSION => {
87+
#[allow(clippy::disallowed_methods)]
88+
let process_version = Command::new(process_path)
89+
.arg("--version")
90+
.output()
91+
.map(|output| String::from_utf8_lossy(&output.stdout).trim().to_owned())
92+
.unwrap_or_else(|_| "unknown version".to_owned());
93+
err = Some(io::Error::other(format!(
94+
"Your installed proc-macro server is too new for your rust-analyzer. API version: {}, server version: {process_version}. \
8195
This will prevent proc-macro expansion from working. Please consider updating your rust-analyzer to ensure compatibility with your current toolchain.",
82-
version::CURRENT_API_VERSION
83-
)))
84-
}
85-
Ok(v) => {
86-
tracing::info!("Proc-macro server version: {v}");
87-
srv.version = v;
88-
if srv.version >= version::RUST_ANALYZER_SPAN_SUPPORT
89-
&& let Ok(mode) = srv.enable_rust_analyzer_spans()
90-
{
91-
srv.protocol = Protocol::LegacyJson { mode };
96+
version::CURRENT_API_VERSION
97+
)));
98+
}
99+
Ok(v) => {
100+
tracing::info!("Proc-macro server version: {v}");
101+
srv.version = v;
102+
if srv.version >= version::RUST_ANALYZER_SPAN_SUPPORT
103+
&& let Ok(new_mode) = srv.enable_rust_analyzer_spans()
104+
{
105+
match &mut srv.protocol {
106+
Protocol::LegacyJson { mode } | Protocol::LegacyPostcard { mode } => {
107+
*mode = new_mode
108+
}
109+
}
110+
}
111+
tracing::info!("Proc-macro server protocol: {:?}", srv.protocol);
112+
return Ok(srv);
113+
}
114+
Err(e) => {
115+
tracing::info!(%e, "proc-macro version check failed");
116+
err = Some(io::Error::other(format!(
117+
"proc-macro server version check failed: {e}"
118+
)))
92119
}
93-
tracing::info!("Proc-macro server protocol: {:?}", srv.protocol);
94-
Ok(srv)
95-
}
96-
Err(e) => {
97-
tracing::info!(%e, "proc-macro version check failed");
98-
Err(io::Error::other(format!("proc-macro server version check failed: {e}")))
99120
}
100121
}
122+
Err(err.unwrap())
101123
}
102124

103125
/// Returns the server error if the process has exited.
@@ -106,7 +128,7 @@ impl ProcMacroServerProcess {
106128
}
107129

108130
pub(crate) fn use_postcard(&self) -> bool {
109-
matches!(self.protocol, Protocol::Postcard { .. })
131+
matches!(self.protocol, Protocol::LegacyPostcard { .. })
110132
}
111133

112134
/// Retrieves the API version of the proc-macro server.
@@ -118,23 +140,23 @@ impl ProcMacroServerProcess {
118140
pub(crate) fn rust_analyzer_spans(&self) -> bool {
119141
match self.protocol {
120142
Protocol::LegacyJson { mode } => mode == SpanMode::RustAnalyzer,
121-
Protocol::Postcard { mode } => mode == SpanMode::RustAnalyzer,
143+
Protocol::LegacyPostcard { mode } => mode == SpanMode::RustAnalyzer,
122144
}
123145
}
124146

125147
/// Checks the API version of the running proc-macro server.
126148
fn version_check(&self) -> Result<u32, ServerError> {
127149
match self.protocol {
128150
Protocol::LegacyJson { .. } => legacy_protocol::version_check(self),
129-
Protocol::Postcard { .. } => legacy_protocol::version_check(self),
151+
Protocol::LegacyPostcard { .. } => legacy_protocol::version_check(self),
130152
}
131153
}
132154

133155
/// Enable support for rust-analyzer span mode if the server supports it.
134156
fn enable_rust_analyzer_spans(&self) -> Result<SpanMode, ServerError> {
135157
match self.protocol {
136158
Protocol::LegacyJson { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
137-
Protocol::Postcard { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
159+
Protocol::LegacyPostcard { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
138160
}
139161
}
140162

@@ -145,7 +167,7 @@ impl ProcMacroServerProcess {
145167
) -> Result<Result<Vec<(String, ProcMacroKind)>, String>, ServerError> {
146168
match self.protocol {
147169
Protocol::LegacyJson { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
148-
Protocol::Postcard { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
170+
Protocol::LegacyPostcard { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
149171
}
150172
}
151173

@@ -220,8 +242,9 @@ impl Process {
220242
env: impl IntoIterator<
221243
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
222244
>,
245+
format: Option<&str>,
223246
) -> io::Result<Process> {
224-
let child = JodChild(mk_child(path, env)?);
247+
let child = JodChild(mk_child(path, env, format)?);
225248
Ok(Process { child })
226249
}
227250

@@ -241,6 +264,7 @@ fn mk_child<'a>(
241264
extra_env: impl IntoIterator<
242265
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
243266
>,
267+
format: Option<&str>,
244268
) -> io::Result<Child> {
245269
#[allow(clippy::disallowed_methods)]
246270
let mut cmd = Command::new(path);
@@ -250,6 +274,10 @@ fn mk_child<'a>(
250274
(key, None) => cmd.env_remove(key),
251275
};
252276
}
277+
if let Some(format) = format {
278+
cmd.arg("--format");
279+
cmd.arg(format);
280+
}
253281
cmd.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
254282
.stdin(Stdio::piped())
255283
.stdout(Stdio::piped())

crates/rust-analyzer/src/reload.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ impl GlobalState {
700700
};
701701
info!("Using proc-macro server at {path}");
702702

703-
Some(ProcMacroClient::spawn(&path, &env).map_err(|err| {
703+
Some(ProcMacroClient::spawn(&path, &env, ws.toolchain.as_ref()).map_err(|err| {
704704
tracing::error!(
705705
"Failed to run proc-macro server from path {path}, error: {err:?}",
706706
);

0 commit comments

Comments
 (0)