Skip to content

Commit cb8a3be

Browse files
committed
Auto merge of #12835 - fasterthanlime:sysroot-abi, r=fasterthanlime
Introduce proc-macro-srv/sysroot-abi Still a WIP. This change is tracked by: * #12818
2 parents 84a6fac + e591ff3 commit cb8a3be

File tree

14 files changed

+1053
-10
lines changed

14 files changed

+1053
-10
lines changed

Cargo.lock

Lines changed: 27 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
process::ProcMacroProcessSrv,
2727
};
2828

29-
pub use version::{read_dylib_info, RustCInfo};
29+
pub use version::{read_dylib_info, read_version, RustCInfo};
3030

3131
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
3232
pub enum ProcMacroKind {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub struct RustCInfo {
1616
pub channel: String,
1717
pub commit: Option<String>,
1818
pub date: Option<String>,
19+
// something like "rustc 1.58.1 (db9d1b20b 2022-01-20)"
20+
pub version_string: String,
1921
}
2022

2123
/// Read rustc dylib information
@@ -68,7 +70,7 @@ pub fn read_dylib_info(dylib_path: &AbsPath) -> io::Result<RustCInfo> {
6870
}
6971
let version = (version_numbers[0], version_numbers[1], version_numbers[2]);
7072

71-
Ok(RustCInfo { version, channel, commit, date })
73+
Ok(RustCInfo { version, channel, commit, date, version_string: ver_str })
7274
}
7375

7476
/// This is used inside read_version() to locate the ".rustc" section
@@ -102,7 +104,7 @@ fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'
102104
/// * [some more bytes that we don't really care but about still there] :-)
103105
/// Check this issue for more about the bytes layout:
104106
/// <https://github.com/rust-lang/rust-analyzer/issues/6174>
105-
fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
107+
pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
106108
let dylib_file = File::open(dylib_path)?;
107109
let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?;
108110

crates/proc-macro-srv/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ tt = { path = "../tt", version = "0.0.0" }
2424
mbe = { path = "../mbe", version = "0.0.0" }
2525
paths = { path = "../paths", version = "0.0.0" }
2626
proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
27+
crossbeam = "0.8.1"
2728

2829
[dev-dependencies]
2930
expect-test = "1.4.0"
3031

3132
# used as proc macro test targets
3233
proc-macro-test = { path = "../proc-macro-test" }
34+
35+
[features]
36+
sysroot-abi = []

crates/proc-macro-srv/build.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! Determine rustc version `proc-macro-srv` (and thus the sysroot ABI) is
2+
//! build with and make it accessible at runtime for ABI selection.
3+
4+
use std::{env, fs::File, io::Write, path::PathBuf, process::Command};
5+
6+
fn main() {
7+
let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
8+
path.push("rustc_version.rs");
9+
let mut f = File::create(&path).unwrap();
10+
11+
let rustc = env::var("RUSTC").expect("proc-macro-srv's build script expects RUSTC to be set");
12+
let output = Command::new(rustc).arg("--version").output().expect("rustc --version must run");
13+
let version_string = std::str::from_utf8(&output.stdout[..])
14+
.expect("rustc --version output must be UTF-8")
15+
.trim();
16+
17+
write!(
18+
f,
19+
"
20+
#[allow(dead_code)]
21+
pub(crate) const RUSTC_VERSION_STRING: &str = {version_string:?};
22+
"
23+
)
24+
.unwrap();
25+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//! Proc macro ABI
2+
3+
extern crate proc_macro;
4+
5+
#[allow(dead_code)]
6+
#[doc(hidden)]
7+
mod ra_server;
8+
9+
use libloading::Library;
10+
use proc_macro_api::ProcMacroKind;
11+
12+
use super::PanicMessage;
13+
14+
pub(crate) struct Abi {
15+
exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
16+
}
17+
18+
impl From<proc_macro::bridge::PanicMessage> for PanicMessage {
19+
fn from(p: proc_macro::bridge::PanicMessage) -> Self {
20+
Self { message: p.as_str().map(|s| s.to_string()) }
21+
}
22+
}
23+
24+
impl Abi {
25+
pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> {
26+
let macros: libloading::Symbol<'_, &&[proc_macro::bridge::client::ProcMacro]> =
27+
lib.get(symbol_name.as_bytes())?;
28+
Ok(Self { exported_macros: macros.to_vec() })
29+
}
30+
31+
pub fn expand(
32+
&self,
33+
macro_name: &str,
34+
macro_body: &tt::Subtree,
35+
attributes: Option<&tt::Subtree>,
36+
) -> Result<tt::Subtree, PanicMessage> {
37+
let parsed_body = ra_server::TokenStream::with_subtree(macro_body.clone());
38+
39+
let parsed_attributes = attributes.map_or(ra_server::TokenStream::new(), |attr| {
40+
ra_server::TokenStream::with_subtree(attr.clone())
41+
});
42+
43+
for proc_macro in &self.exported_macros {
44+
match proc_macro {
45+
proc_macro::bridge::client::ProcMacro::CustomDerive {
46+
trait_name, client, ..
47+
} if *trait_name == macro_name => {
48+
let res = client.run(
49+
&proc_macro::bridge::server::SameThread,
50+
ra_server::RustAnalyzer::default(),
51+
parsed_body,
52+
true,
53+
);
54+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
55+
}
56+
proc_macro::bridge::client::ProcMacro::Bang { name, client }
57+
if *name == macro_name =>
58+
{
59+
let res = client.run(
60+
&proc_macro::bridge::server::SameThread,
61+
ra_server::RustAnalyzer::default(),
62+
parsed_body,
63+
true,
64+
);
65+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
66+
}
67+
proc_macro::bridge::client::ProcMacro::Attr { name, client }
68+
if *name == macro_name =>
69+
{
70+
let res = client.run(
71+
&proc_macro::bridge::server::SameThread,
72+
ra_server::RustAnalyzer::default(),
73+
parsed_attributes,
74+
parsed_body,
75+
true,
76+
);
77+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
78+
}
79+
_ => continue,
80+
}
81+
}
82+
83+
Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
84+
}
85+
86+
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
87+
self.exported_macros
88+
.iter()
89+
.map(|proc_macro| match proc_macro {
90+
proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
91+
(trait_name.to_string(), ProcMacroKind::CustomDerive)
92+
}
93+
proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
94+
(name.to_string(), ProcMacroKind::FuncLike)
95+
}
96+
proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
97+
(name.to_string(), ProcMacroKind::Attr)
98+
}
99+
})
100+
.collect()
101+
}
102+
}

0 commit comments

Comments
 (0)