Skip to content

Commit 62622c6

Browse files
bors[bot]alexjg
andauthored
Merge #9550
9550: Proc macro multi abi proof of concept r=matklad a=alexjg #8925 was irritating me so I thought I would have a bash at fixing it. What I've done here is copy the `crates/proc_macro_srv/src/proc_macro` code (which is copied from `<RUST>/library/proc_macro`) to `crates/proc_macro_srv/src/proc_macro_nightly` and the modified the nightly version to include the changes from #9047 and https://github.com/yotamofek/rust-analyzer/commit/aeb7b183a2302af968f1110fb3cbd00c76a34974 This gives us the code to support both stable and nightly ABIs. Then we use the `proc_macro_api::version::read_dylib_info` to determine which version of the ABI to load when creating a `ProcMacroLibraryLibLoading` (which is now an enum). This seems to work for me. The code could be cleaned up but I wanted to see if the approach makes sense before I spend more time on it. I've split the change into two commits, the first is just copying and modifying the `proc_macro` crate, the second contains most of the interesting work around figuring out which ABI to use. Co-authored-by: Alex Good <[email protected]> Co-authored-by: alexjg <[email protected]>
2 parents 7988c80 + e240eb6 commit 62622c6

File tree

28 files changed

+4280
-114
lines changed

28 files changed

+4280
-114
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//! Macro ABI for version 1.47 of rustc
2+
3+
#[allow(dead_code)]
4+
#[doc(hidden)]
5+
mod proc_macro;
6+
7+
#[allow(dead_code)]
8+
#[doc(hidden)]
9+
mod rustc_server;
10+
use libloading::Library;
11+
12+
use proc_macro_api::ProcMacroKind;
13+
14+
use super::PanicMessage;
15+
16+
pub use rustc_server::TokenStream;
17+
18+
pub(crate) struct Abi {
19+
exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
20+
}
21+
22+
impl From<proc_macro::bridge::PanicMessage> for PanicMessage {
23+
fn from(p: proc_macro::bridge::PanicMessage) -> Self {
24+
Self { message: p.as_str().map(|s| s.to_string()) }
25+
}
26+
}
27+
28+
impl Abi {
29+
pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> {
30+
let macros: libloading::Symbol<&&[proc_macro::bridge::client::ProcMacro]> =
31+
lib.get(symbol_name.as_bytes())?;
32+
Ok(Self { exported_macros: macros.to_vec() })
33+
}
34+
35+
pub fn expand(
36+
&self,
37+
macro_name: &str,
38+
macro_body: &tt::Subtree,
39+
attributes: Option<&tt::Subtree>,
40+
) -> Result<tt::Subtree, PanicMessage> {
41+
let parsed_body = rustc_server::TokenStream::with_subtree(macro_body.clone());
42+
43+
let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| {
44+
rustc_server::TokenStream::with_subtree(attr.clone())
45+
});
46+
47+
for proc_macro in &self.exported_macros {
48+
match proc_macro {
49+
proc_macro::bridge::client::ProcMacro::CustomDerive {
50+
trait_name, client, ..
51+
} if *trait_name == macro_name => {
52+
let res = client.run(
53+
&proc_macro::bridge::server::SameThread,
54+
rustc_server::Rustc::default(),
55+
parsed_body,
56+
false,
57+
);
58+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
59+
}
60+
proc_macro::bridge::client::ProcMacro::Bang { name, client }
61+
if *name == macro_name =>
62+
{
63+
let res = client.run(
64+
&proc_macro::bridge::server::SameThread,
65+
rustc_server::Rustc::default(),
66+
parsed_body,
67+
false,
68+
);
69+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
70+
}
71+
proc_macro::bridge::client::ProcMacro::Attr { name, client }
72+
if *name == macro_name =>
73+
{
74+
let res = client.run(
75+
&proc_macro::bridge::server::SameThread,
76+
rustc_server::Rustc::default(),
77+
parsed_attributes,
78+
parsed_body,
79+
false,
80+
);
81+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
82+
}
83+
_ => continue,
84+
}
85+
}
86+
87+
Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
88+
}
89+
90+
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
91+
self.exported_macros
92+
.iter()
93+
.map(|proc_macro| match proc_macro {
94+
proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
95+
(trait_name.to_string(), ProcMacroKind::CustomDerive)
96+
}
97+
proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
98+
(name.to_string(), ProcMacroKind::FuncLike)
99+
}
100+
proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
101+
(name.to_string(), ProcMacroKind::Attr)
102+
}
103+
})
104+
.collect()
105+
}
106+
}

crates/proc_macro_srv/src/proc_macro/bridge/client.rs renamed to crates/proc_macro_srv/src/abis/abi_1_47/proc_macro/bridge/client.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/client.rs>
44
//! augmented with removing unstable features
55
6+
use super::super::TokenStream as CrateTokenStream;
67
use super::*;
78

89
macro_rules! define_handles {
@@ -401,26 +402,26 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
401402
b
402403
}
403404

404-
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
405-
pub fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
405+
impl Client<fn(CrateTokenStream) -> CrateTokenStream> {
406+
pub fn expand1(f: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
406407
extern "C" fn run(
407408
bridge: Bridge<'_>,
408-
f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
409+
f: impl FnOnce(CrateTokenStream) -> CrateTokenStream,
409410
) -> Buffer<u8> {
410-
run_client(bridge, |input| f(crate::TokenStream(input)).0)
411+
run_client(bridge, |input| f(CrateTokenStream(input)).0)
411412
}
412413
Client { get_handle_counters: HandleCounters::get, run, f }
413414
}
414415
}
415416

416-
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
417-
pub fn expand2(f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream) -> Self {
417+
impl Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream> {
418+
pub fn expand2(f: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream) -> Self {
418419
extern "C" fn run(
419420
bridge: Bridge<'_>,
420-
f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
421+
f: impl FnOnce(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
421422
) -> Buffer<u8> {
422423
run_client(bridge, |(input, input2)| {
423-
f(crate::TokenStream(input), crate::TokenStream(input2)).0
424+
f(CrateTokenStream(input), CrateTokenStream(input2)).0
424425
})
425426
}
426427
Client { get_handle_counters: HandleCounters::get, run, f }
@@ -433,17 +434,17 @@ pub enum ProcMacro {
433434
CustomDerive {
434435
trait_name: &'static str,
435436
attributes: &'static [&'static str],
436-
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
437+
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
437438
},
438439

439440
Attr {
440441
name: &'static str,
441-
client: Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream>,
442+
client: Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream>,
442443
},
443444

444445
Bang {
445446
name: &'static str,
446-
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
447+
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
447448
},
448449
}
449450

@@ -465,19 +466,19 @@ impl ProcMacro {
465466
pub fn custom_derive(
466467
trait_name: &'static str,
467468
attributes: &'static [&'static str],
468-
expand: fn(crate::TokenStream) -> crate::TokenStream,
469+
expand: fn(CrateTokenStream) -> CrateTokenStream,
469470
) -> Self {
470471
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
471472
}
472473

473474
pub fn attr(
474475
name: &'static str,
475-
expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
476+
expand: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
476477
) -> Self {
477478
ProcMacro::Attr { name, client: Client::expand2(expand) }
478479
}
479480

480-
pub fn bang(name: &'static str, expand: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
481+
pub fn bang(name: &'static str, expand: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
481482
ProcMacro::Bang { name, client: Client::expand1(expand) }
482483
}
483484
}

crates/proc_macro_srv/src/proc_macro/bridge/mod.rs renamed to crates/proc_macro_srv/src/abis/abi_1_47/proc_macro/bridge/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
1414
#![deny(unsafe_code)]
1515

16-
pub use crate::proc_macro::{Delimiter, Level, LineColumn, Spacing};
16+
pub use super::{Delimiter, Level, LineColumn, Spacing};
1717
use std::fmt;
1818
use std::hash::Hash;
1919
use std::marker;

crates/proc_macro_srv/src/proc_macro/bridge/server.rs renamed to crates/proc_macro_srv/src/abis/abi_1_47/proc_macro/bridge/server.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
44
//! augmented with removing unstable features
55
6+
use super::super::TokenStream as ProcMacroTokenStream;
67
use super::*;
78

89
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
@@ -308,7 +309,7 @@ fn run_server<
308309
Result::decode(&mut &b[..], &mut dispatcher.handle_store)
309310
}
310311

311-
impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
312+
impl client::Client<fn(ProcMacroTokenStream) -> ProcMacroTokenStream> {
312313
pub fn run<S: Server>(
313314
&self,
314315
strategy: &impl ExecutionStrategy,
@@ -330,7 +331,7 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
330331
}
331332
}
332333

333-
impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
334+
impl client::Client<fn(ProcMacroTokenStream, ProcMacroTokenStream) -> ProcMacroTokenStream> {
334335
pub fn run<S: Server>(
335336
&self,
336337
strategy: &impl ExecutionStrategy,

crates/proc_macro_srv/src/proc_macro/diagnostic.rs renamed to crates/proc_macro_srv/src/abis/abi_1_47/proc_macro/diagnostic.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/diagnostic.rs>
44
//! augmented with removing unstable features
55
6-
use crate::proc_macro::Span;
6+
use super::Span;
77

88
/// An enum representing a diagnostic level.
99
#[derive(Copy, Clone, Debug)]
@@ -146,15 +146,15 @@ impl Diagnostic {
146146

147147
/// Emit the diagnostic.
148148
pub fn emit(self) {
149-
fn to_internal(spans: Vec<Span>) -> crate::proc_macro::bridge::client::MultiSpan {
150-
let mut multi_span = crate::proc_macro::bridge::client::MultiSpan::new();
149+
fn to_internal(spans: Vec<Span>) -> super::bridge::client::MultiSpan {
150+
let mut multi_span = super::bridge::client::MultiSpan::new();
151151
for span in spans {
152152
multi_span.push(span.0);
153153
}
154154
multi_span
155155
}
156156

157-
let mut diag = crate::proc_macro::bridge::client::Diagnostic::new(
157+
let mut diag = super::bridge::client::Diagnostic::new(
158158
self.level,
159159
&self.message[..],
160160
to_internal(self.spans),

0 commit comments

Comments
 (0)