Skip to content

Commit 993bda7

Browse files
committed
Fix rust-analyzer-proc-macro-srv
1 parent 7edb1c0 commit 993bda7

8 files changed

Lines changed: 103 additions & 203 deletions

File tree

compiler/rustc_codegen_ssa/src/back/metadata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use super::apple;
3636
/// <dd>The metadata can be found in the `.rustc` section of the shared library.</dd>
3737
/// </dl>
3838
#[derive(Debug)]
39-
pub(crate) struct DefaultMetadataLoader;
39+
pub struct DefaultMetadataLoader;
4040

4141
static AIX_METADATA_SYMBOL_NAME: &'static str = "__aix_rust_metadata";
4242

compiler/rustc_metadata/src/locator.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ use tracing::{debug, info};
236236

237237
use crate::creader::{Library, MetadataLoader};
238238
use crate::errors;
239-
use crate::rmeta::{METADATA_HEADER, MetadataBlob, rustc_version};
239+
use crate::rmeta::{METADATA_HEADER, MetadataBlob, ProcMacroKind, rustc_version};
240240

241241
#[derive(Clone)]
242242
pub(crate) struct CrateLocator<'a> {
@@ -821,7 +821,7 @@ fn get_metadata_section<'p>(
821821
crate_name: Option<Symbol>,
822822
) -> Result<MetadataBlob, MetadataError<'p>> {
823823
if !filename.exists() {
824-
return Err(MetadataError::NotPresent(filename));
824+
return Err(MetadataError::NotPresent(filename.into()));
825825
}
826826
let raw_bytes = match flavor {
827827
CrateFlavor::Rlib => {
@@ -978,6 +978,20 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor {
978978
}
979979
}
980980

981+
/// A function to get information about all macros inside a proc-macro crate.
982+
///
983+
/// Used by rust-analyzer-proc-macro-srv.
984+
pub fn get_proc_macro_info<'p>(
985+
target: &Target,
986+
path: &'p Path,
987+
metadata_loader: &dyn MetadataLoader,
988+
cfg_version: &'static str,
989+
) -> Result<Vec<ProcMacroKind>, MetadataError<'p>> {
990+
let metadata =
991+
get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None)?;
992+
Ok(metadata.get_proc_macro_info())
993+
}
994+
981995
// ------------------------------------------ Error reporting -------------------------------------
982996

983997
#[derive(Clone, Debug)]
@@ -1024,9 +1038,10 @@ pub(crate) enum CrateError {
10241038
NotFound(Symbol),
10251039
}
10261040

1027-
enum MetadataError<'a> {
1041+
#[derive(Debug)]
1042+
pub enum MetadataError<'a> {
10281043
/// The file was missing.
1029-
NotPresent(&'a Path),
1044+
NotPresent(Cow<'a, Path>),
10301045
/// The file was present and invalid.
10311046
LoadFailure(String),
10321047
/// The file was present, but compiled with a different rustc version.

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,16 @@ impl MetadataBlob {
930930

931931
Ok(())
932932
}
933+
934+
pub(crate) fn get_proc_macro_info(&self) -> Vec<ProcMacroKind> {
935+
self.get_root()
936+
.proc_macro_data
937+
.unwrap()
938+
.macros
939+
.decode(self)
940+
.map(|(_id, kind)| kind.decode(self))
941+
.collect::<Vec<_>>()
942+
}
933943
}
934944

935945
impl CrateRoot {

src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ line-index.workspace = true
3535
proc-macro-test.path = "./proc-macro-test"
3636

3737
[features]
38-
default = []
39-
# default = ["in-rust-tree"]
38+
default = ["in-rust-tree"]
4039
in-rust-tree = []
4140

4241
[lints]

src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
//! Handles dynamic library loading for proc macro
22
33
mod proc_macros;
4-
mod version;
54

5+
use rustc_codegen_ssa::back::metadata::DefaultMetadataLoader;
6+
use rustc_interface::util::rustc_version_str;
7+
use rustc_metadata::locator::MetadataError;
68
use rustc_proc_macro::bridge;
9+
use rustc_session::config::host_tuple;
10+
use rustc_target::spec::{Target, TargetTuple};
11+
use std::path::Path;
712
use std::{fmt, fs, io, time::SystemTime};
813
use temp_dir::TempDir;
914

@@ -13,7 +18,8 @@ use paths::{Utf8Path, Utf8PathBuf};
1318

1419
use crate::{
1520
PanicMessage, ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan, TrackedEnv,
16-
dylib::proc_macros::ProcMacros, token_stream::TokenStream,
21+
dylib::proc_macros::{ProcMacroClients, ProcMacros},
22+
token_stream::TokenStream,
1723
};
1824

1925
pub(crate) struct Expander {
@@ -76,18 +82,15 @@ impl Expander {
7682
pub enum LoadProcMacroDylibError {
7783
Io(io::Error),
7884
LibLoading(libloading::Error),
79-
AbiMismatch(String),
85+
MetadataError(MetadataError<'static>),
8086
}
8187

8288
impl fmt::Display for LoadProcMacroDylibError {
8389
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8490
match self {
8591
Self::Io(e) => e.fmt(f),
86-
Self::AbiMismatch(v) => {
87-
use crate::RUSTC_VERSION_STRING;
88-
write!(f, "mismatched ABI expected: `{RUSTC_VERSION_STRING}`, got `{v}`")
89-
}
9092
Self::LibLoading(e) => e.fmt(f),
93+
Self::MetadataError(e) => e.fmt(f),
9194
}
9295
}
9396
}
@@ -104,25 +107,44 @@ impl From<libloading::Error> for LoadProcMacroDylibError {
104107
}
105108
}
106109

110+
impl From<MetadataError<'_>> for LoadProcMacroDylibError {
111+
fn from(e: MetadataError<'_>) -> Self {
112+
LoadProcMacroDylibError::MetadataError(match e {
113+
MetadataError::NotPresent(path) => MetadataError::NotPresent(path.into_owned().into()),
114+
MetadataError::LoadFailure(err) => MetadataError::LoadFailure(err),
115+
MetadataError::VersionMismatch { expected_version, found_version } => {
116+
MetadataError::VersionMismatch { expected_version, found_version }
117+
}
118+
})
119+
}
120+
}
121+
107122
struct ProcMacroLibrary {
108-
// 'static is actually the lifetime of library, so make sure this drops before _lib
109-
proc_macros: &'static ProcMacros,
123+
// this contains references to the library, so make sure this drops before _lib
124+
proc_macros: ProcMacros,
110125
// Hold on to the library so it doesn't unload
111126
_lib: Library,
112127
}
113128

114129
impl ProcMacroLibrary {
115130
fn open(path: &Utf8Path) -> Result<Self, LoadProcMacroDylibError> {
131+
let proc_macro_kinds = rustc_span::create_default_session_globals_then(|| {
132+
let (target, _) =
133+
Target::search(&TargetTuple::from_tuple(host_tuple()), Path::new(""), false)
134+
.unwrap();
135+
rustc_metadata::locator::get_proc_macro_info(
136+
&target,
137+
path.as_ref(),
138+
&DefaultMetadataLoader,
139+
rustc_version_str().unwrap_or("unknown"),
140+
)
141+
})?;
142+
116143
let file = fs::File::open(path)?;
117144
#[allow(clippy::undocumented_unsafe_blocks)] // FIXME
118145
let file = unsafe { memmap2::Mmap::map(&file) }?;
119146
let obj = object::File::parse(&*file)
120147
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
121-
let version_info = version::read_dylib_info(&obj)?;
122-
if version_info.version_string != crate::RUSTC_VERSION_STRING {
123-
return Err(LoadProcMacroDylibError::AbiMismatch(version_info.version_string));
124-
}
125-
126148
let symbol_name =
127149
find_registrar_symbol(&obj).map_err(invalid_data_err)?.ok_or_else(|| {
128150
invalid_data_err(format!("Cannot find registrar symbol in file {path}"))
@@ -135,9 +157,12 @@ impl ProcMacroLibrary {
135157
// due to self-referentiality
136158
// But we make sure that we do not drop it before the symbol is dropped
137159
let proc_macros =
138-
unsafe { lib.get::<&'static &'static ProcMacros>(symbol_name.as_bytes()) };
160+
unsafe { lib.get::<&'static &'static ProcMacroClients>(symbol_name.as_bytes()) };
139161
match proc_macros {
140-
Ok(proc_macros) => Ok(ProcMacroLibrary { proc_macros: *proc_macros, _lib: lib }),
162+
Ok(proc_macros) => Ok(ProcMacroLibrary {
163+
proc_macros: ProcMacros::new(*proc_macros, proc_macro_kinds),
164+
_lib: lib,
165+
}),
141166
Err(e) => Err(e.into()),
142167
}
143168
}

src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,24 @@ use crate::{
55
use rustc_proc_macro::bridge;
66

77
#[repr(transparent)]
8-
pub(crate) struct ProcMacros([bridge::client::ProcMacro]);
8+
pub(crate) struct ProcMacroClients([bridge::client::Client]);
99

1010
impl From<bridge::PanicMessage> for crate::PanicMessage {
1111
fn from(p: bridge::PanicMessage) -> Self {
1212
Self { message: p.into_string() }
1313
}
1414
}
1515

16+
pub(crate) struct ProcMacros(Vec<(bridge::client::Client, rustc_metadata::ProcMacroKind)>);
17+
1618
impl ProcMacros {
19+
pub(super) fn new(
20+
clients: &ProcMacroClients,
21+
kinds: Vec<rustc_metadata::ProcMacroKind>,
22+
) -> Self {
23+
ProcMacros(clients.0.iter().copied().zip(kinds).collect::<Vec<_>>())
24+
}
25+
1726
pub(crate) fn expand<'a, S: ProcMacroSrvSpan>(
1827
&self,
1928
macro_name: &str,
@@ -27,10 +36,10 @@ impl ProcMacros {
2736
) -> Result<TokenStream<S>, crate::PanicMessage> {
2837
let parsed_attributes = attribute.unwrap_or_default();
2938

30-
for proc_macro in &self.0 {
31-
match proc_macro {
32-
bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
33-
if *trait_name == macro_name =>
39+
for (client, kind) in &self.0 {
40+
match kind {
41+
rustc_metadata::ProcMacroKind::CustomDerive { trait_name, .. }
42+
if trait_name.as_str() == macro_name =>
3443
{
3544
let res = client.run1(
3645
&bridge::server::SAME_THREAD,
@@ -40,7 +49,7 @@ impl ProcMacros {
4049
);
4150
return res.map_err(crate::PanicMessage::from);
4251
}
43-
bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
52+
rustc_metadata::ProcMacroKind::Bang { name } if name.as_str() == macro_name => {
4453
let res = client.run1(
4554
&bridge::server::SAME_THREAD,
4655
S::make_server(call_site, def_site, mixed_site, tracked_env, callback),
@@ -49,7 +58,7 @@ impl ProcMacros {
4958
);
5059
return res.map_err(crate::PanicMessage::from);
5160
}
52-
bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
61+
rustc_metadata::ProcMacroKind::Attr { name } if name.as_str() == macro_name => {
5362
let res = client.run2(
5463
&bridge::server::SAME_THREAD,
5564
S::make_server(call_site, def_site, mixed_site, tracked_env, callback),
@@ -67,12 +76,16 @@ impl ProcMacros {
6776
}
6877

6978
pub(crate) fn list_macros(&self) -> impl Iterator<Item = (&str, ProcMacroKind)> {
70-
self.0.iter().map(|proc_macro| match *proc_macro {
71-
bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
72-
(trait_name, ProcMacroKind::CustomDerive)
79+
self.0.iter().map(|(_client, kind)| match kind {
80+
rustc_metadata::ProcMacroKind::CustomDerive { trait_name, .. } => {
81+
(trait_name.as_str(), ProcMacroKind::CustomDerive)
82+
}
83+
rustc_metadata::ProcMacroKind::Bang { name, .. } => {
84+
(name.as_str(), ProcMacroKind::Bang)
85+
}
86+
rustc_metadata::ProcMacroKind::Attr { name, .. } => {
87+
(name.as_str(), ProcMacroKind::Attr)
7388
}
74-
bridge::client::ProcMacro::Bang { name, .. } => (name, ProcMacroKind::Bang),
75-
bridge::client::ProcMacro::Attr { name, .. } => (name, ProcMacroKind::Attr),
7689
})
7790
}
7891
}

0 commit comments

Comments
 (0)