Skip to content

Commit 6133e27

Browse files
committed
Auto merge of #14070 - Veykril:proc-macro-api, r=Veykril
Implement proc-macro-api versioning So as it stands, we can't really change the proc-macro-api protocol at all without breaking all proc-macro servers again. To somewhat alleviate this we can move the supported ABI mess over to the proc-macro-api now by supporting multiple versions there (versions defined by us at least, not by rustc). Since the proc-macro-api protocol has no versioning scheme at the moment though, the best we can do here is add a new request to query the version from a server. Due to how the server currently works though, if it encounters an unknown request it will exit, meaning we can check if it is a server without support by checking if it exited after our version check request, that way we can support the current circulating server as well. We need this since our span type will change from `TokenId` to something else at some point, but for that to work we need to comply with that the server expects. So knowing the version the server is using we can decide whether to send our new span data, or the tokenid (assuming we keep that information with our span data as well, alternatively we send irrelevant tokenids). That way we can keep old servers working while the user installations slowly migrate to newer servers that support the new spandata.
2 parents 46846ea + 8e998c4 commit 6133e27

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl ProcMacroServer {
115115
/// Spawns an external process as the proc macro server and returns a client connected to it.
116116
pub fn spawn(
117117
process_path: AbsPathBuf,
118-
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
118+
args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
119119
) -> io::Result<ProcMacroServer> {
120120
let process = ProcMacroProcessSrv::run(process_path, args)?;
121121
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
@@ -174,7 +174,7 @@ impl ProcMacro {
174174
let response = self.process.lock().unwrap_or_else(|e| e.into_inner()).send_task(request)?;
175175
match response {
176176
msg::Response::ExpandMacro(it) => Ok(it.map(FlatTree::to_subtree)),
177-
msg::Response::ListMacros { .. } => {
177+
msg::Response::ListMacros(..) | msg::Response::ApiVersionCheck(..) => {
178178
Err(ServerError { message: "unexpected response".to_string(), io: None })
179179
}
180180
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,21 @@ use crate::ProcMacroKind;
1212

1313
pub use crate::msg::flat::FlatTree;
1414

15+
pub const NO_VERSION_CHECK_VERSION: u32 = 0;
16+
pub const CURRENT_API_VERSION: u32 = 1;
17+
1518
#[derive(Debug, Serialize, Deserialize)]
1619
pub enum Request {
1720
ListMacros { dylib_path: PathBuf },
1821
ExpandMacro(ExpandMacro),
22+
ApiVersionCheck {},
1923
}
2024

2125
#[derive(Debug, Serialize, Deserialize)]
2226
pub enum Response {
2327
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
2428
ExpandMacro(Result<FlatTree, PanicMessage>),
29+
ApiVersionCheck(u32),
2530
}
2631

2732
#[derive(Debug, Serialize, Deserialize)]

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

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use paths::{AbsPath, AbsPathBuf};
1010
use stdx::JodChild;
1111

1212
use crate::{
13-
msg::{Message, Request, Response},
13+
msg::{Message, Request, Response, CURRENT_API_VERSION},
1414
ProcMacroKind, ServerError,
1515
};
1616

@@ -19,19 +19,52 @@ pub(crate) struct ProcMacroProcessSrv {
1919
_process: Process,
2020
stdin: ChildStdin,
2121
stdout: BufReader<ChildStdout>,
22+
version: u32,
2223
}
2324

2425
impl ProcMacroProcessSrv {
2526
pub(crate) fn run(
2627
process_path: AbsPathBuf,
27-
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
28+
args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
2829
) -> io::Result<ProcMacroProcessSrv> {
29-
let mut process = Process::run(process_path, args)?;
30-
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
30+
let create_srv = || {
31+
let mut process = Process::run(process_path.clone(), args.clone())?;
32+
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
33+
34+
io::Result::Ok(ProcMacroProcessSrv { _process: process, stdin, stdout, version: 0 })
35+
};
36+
let mut srv = create_srv()?;
37+
tracing::info!("sending version check");
38+
match srv.version_check() {
39+
Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::new(
40+
io::ErrorKind::Other,
41+
format!(
42+
"proc-macro server's api version ({}) is newer than rust-analyzer's ({})",
43+
v, CURRENT_API_VERSION
44+
),
45+
)),
46+
Ok(v) => {
47+
tracing::info!("got version {v}");
48+
srv.version = v;
49+
Ok(srv)
50+
}
51+
Err(e) => {
52+
tracing::info!(%e, "proc-macro version check failed, restarting and assuming version 0");
53+
create_srv()
54+
}
55+
}
56+
}
3157

32-
let srv = ProcMacroProcessSrv { _process: process, stdin, stdout };
58+
pub(crate) fn version_check(&mut self) -> Result<u32, ServerError> {
59+
let request = Request::ApiVersionCheck {};
60+
let response = self.send_task(request)?;
3361

34-
Ok(srv)
62+
match response {
63+
Response::ApiVersionCheck(version) => Ok(version),
64+
Response::ExpandMacro { .. } | Response::ListMacros { .. } => {
65+
Err(ServerError { message: "unexpected response".to_string(), io: None })
66+
}
67+
}
3568
}
3669

3770
pub(crate) fn find_proc_macros(
@@ -44,7 +77,7 @@ impl ProcMacroProcessSrv {
4477

4578
match response {
4679
Response::ListMacros(it) => Ok(it),
47-
Response::ExpandMacro { .. } => {
80+
Response::ExpandMacro { .. } | Response::ApiVersionCheck { .. } => {
4881
Err(ServerError { message: "unexpected response".to_string(), io: None })
4982
}
5083
}

crates/proc-macro-srv/src/cli.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub fn run() -> io::Result<()> {
1515
msg::Response::ListMacros(srv.list_macros(&dylib_path))
1616
}
1717
msg::Request::ExpandMacro(task) => msg::Response::ExpandMacro(srv.expand(task)),
18+
msg::Request::ApiVersionCheck {} => {
19+
msg::Response::ApiVersionCheck(proc_macro_api::msg::CURRENT_API_VERSION)
20+
}
1821
};
1922
write_response(res)?
2023
}

0 commit comments

Comments
 (0)