From da79572be79f593dbd09f43d9dd9611c1569051f Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:18:56 +0200 Subject: [PATCH 1/8] Add internal ABI, relying on rustc's own version of proc_macro --- .../src/abis/abi_internal/mod.rs | 102 +++ .../src/abis/abi_internal/rustc_server.rs | 819 ++++++++++++++++++ crates/proc-macro-srv/src/abis/mod.rs | 2 + crates/proc-macro-srv/src/lib.rs | 3 + 4 files changed, 926 insertions(+) create mode 100644 crates/proc-macro-srv/src/abis/abi_internal/mod.rs create mode 100644 crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs diff --git a/crates/proc-macro-srv/src/abis/abi_internal/mod.rs b/crates/proc-macro-srv/src/abis/abi_internal/mod.rs new file mode 100644 index 000000000000..85dcbdbfc2ba --- /dev/null +++ b/crates/proc-macro-srv/src/abis/abi_internal/mod.rs @@ -0,0 +1,102 @@ +//! Macro ABI for version internal of rustc + +extern crate proc_macro; + +#[allow(dead_code)] +#[doc(hidden)] +mod rustc_server; + +use libloading::Library; +use proc_macro_api::ProcMacroKind; + +use super::PanicMessage; + +pub(crate) struct Abi { + exported_macros: Vec, +} + +impl From for PanicMessage { + fn from(p: proc_macro::bridge::PanicMessage) -> Self { + Self { message: p.as_str().map(|s| s.to_string()) } + } +} + +impl Abi { + pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result { + let macros: libloading::Symbol<&&[proc_macro::bridge::client::ProcMacro]> = + lib.get(symbol_name.as_bytes())?; + Ok(Self { exported_macros: macros.to_vec() }) + } + + pub fn expand( + &self, + macro_name: &str, + macro_body: &tt::Subtree, + attributes: Option<&tt::Subtree>, + ) -> Result { + let parsed_body = rustc_server::TokenStream::with_subtree(macro_body.clone()); + + let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| { + rustc_server::TokenStream::with_subtree(attr.clone()) + }); + + for proc_macro in &self.exported_macros { + match proc_macro { + proc_macro::bridge::client::ProcMacro::CustomDerive { + trait_name, client, .. + } if *trait_name == macro_name => { + let res = client.run( + &proc_macro::bridge::server::SameThread, + rustc_server::Rustc::default(), + parsed_body, + true, + ); + return res.map(|it| it.into_subtree()).map_err(PanicMessage::from); + } + proc_macro::bridge::client::ProcMacro::Bang { name, client } + if *name == macro_name => + { + let res = client.run( + &proc_macro::bridge::server::SameThread, + rustc_server::Rustc::default(), + parsed_body, + true, + ); + return res.map(|it| it.into_subtree()).map_err(PanicMessage::from); + } + proc_macro::bridge::client::ProcMacro::Attr { name, client } + if *name == macro_name => + { + let res = client.run( + &proc_macro::bridge::server::SameThread, + rustc_server::Rustc::default(), + parsed_attributes, + parsed_body, + true, + ); + return res.map(|it| it.into_subtree()).map_err(PanicMessage::from); + } + _ => continue, + } + } + + Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into()) + } + + pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> { + self.exported_macros + .iter() + .map(|proc_macro| match proc_macro { + proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => { + (trait_name.to_string(), ProcMacroKind::CustomDerive) + } + proc_macro::bridge::client::ProcMacro::Bang { name, .. } => { + (name.to_string(), ProcMacroKind::FuncLike) + } + proc_macro::bridge::client::ProcMacro::Attr { name, .. } => { + (name.to_string(), ProcMacroKind::Attr) + } + }) + .collect() + } +} diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs new file mode 100644 index 000000000000..5c596bc0e62a --- /dev/null +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -0,0 +1,819 @@ +//! Rustc proc-macro server implementation with tt +//! +//! Based on idea from +//! The lib-proc-macro server backend is `TokenStream`-agnostic, such that +//! we could provide any TokenStream implementation. +//! The original idea from fedochet is using proc-macro2 as backend, +//! we use tt instead for better integration with RA. +//! +//! FIXME: No span and source file information is implemented yet + +use super::proc_macro::bridge::{self, server}; + +use std::collections::HashMap; +use std::hash::Hash; +use std::iter::FromIterator; +use std::ops::Bound; +use std::{ascii, vec::IntoIter}; + +type Group = tt::Subtree; +type TokenTree = tt::TokenTree; +type Punct = tt::Punct; +type Spacing = tt::Spacing; +type Literal = tt::Literal; +type Span = tt::TokenId; + +#[derive(Debug, Clone)] +pub struct TokenStream { + pub token_trees: Vec, +} + +impl TokenStream { + pub fn new() -> Self { + TokenStream { token_trees: Default::default() } + } + + pub fn with_subtree(subtree: tt::Subtree) -> Self { + if subtree.delimiter.is_some() { + TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] } + } else { + TokenStream { token_trees: subtree.token_trees } + } + } + + pub fn into_subtree(self) -> tt::Subtree { + tt::Subtree { delimiter: None, token_trees: self.token_trees } + } + + pub fn is_empty(&self) -> bool { + self.token_trees.is_empty() + } +} + +/// Creates a token stream containing a single token tree. +impl From for TokenStream { + fn from(tree: TokenTree) -> TokenStream { + TokenStream { token_trees: vec![tree] } + } +} + +/// Collects a number of token trees into a single stream. +impl FromIterator for TokenStream { + fn from_iter>(trees: I) -> Self { + trees.into_iter().map(TokenStream::from).collect() + } +} + +/// A "flattening" operation on token streams, collects token trees +/// from multiple token streams into a single stream. +impl FromIterator for TokenStream { + fn from_iter>(streams: I) -> Self { + let mut builder = TokenStreamBuilder::new(); + streams.into_iter().for_each(|stream| builder.push(stream)); + builder.build() + } +} + +impl Extend for TokenStream { + fn extend>(&mut self, trees: I) { + self.extend(trees.into_iter().map(TokenStream::from)); + } +} + +impl Extend for TokenStream { + fn extend>(&mut self, streams: I) { + for item in streams { + for tkn in item { + match tkn { + tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { + self.token_trees.extend(subtree.token_trees); + } + _ => { + self.token_trees.push(tkn); + } + } + } + } + } +} + +#[derive(Clone)] +pub struct SourceFile { + // FIXME stub +} + +type Level = super::proc_macro::Level; +type LineColumn = super::proc_macro::LineColumn; + +/// A structure representing a diagnostic message and associated children +/// messages. +#[derive(Clone, Debug)] +pub struct Diagnostic { + level: Level, + message: String, + spans: Vec, + children: Vec, +} + +impl Diagnostic { + /// Creates a new diagnostic with the given `level` and `message`. + pub fn new>(level: Level, message: T) -> Diagnostic { + Diagnostic { level, message: message.into(), spans: vec![], children: vec![] } + } +} + +// Rustc Server Ident has to be `Copyable` +// We use a stub here for bypassing +#[derive(Hash, Eq, PartialEq, Copy, Clone)] +pub struct IdentId(u32); + +#[derive(Clone, Hash, Eq, PartialEq)] +struct IdentData(tt::Ident); + +#[derive(Default)] +struct IdentInterner { + idents: HashMap, + ident_data: Vec, +} + +impl IdentInterner { + fn intern(&mut self, data: &IdentData) -> u32 { + if let Some(index) = self.idents.get(data) { + return *index; + } + + let index = self.idents.len() as u32; + self.ident_data.push(data.clone()); + self.idents.insert(data.clone(), index); + index + } + + fn get(&self, index: u32) -> &IdentData { + &self.ident_data[index as usize] + } + + #[allow(unused)] + fn get_mut(&mut self, index: u32) -> &mut IdentData { + self.ident_data.get_mut(index as usize).expect("Should be consistent") + } +} + +pub struct TokenStreamBuilder { + acc: TokenStream, +} + +/// Public implementation details for the `TokenStream` type, such as iterators. +pub mod token_stream { + use std::str::FromStr; + + use super::{TokenStream, TokenTree}; + + /// An iterator over `TokenStream`'s `TokenTree`s. + /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups, + /// and returns whole groups as token trees. + impl IntoIterator for TokenStream { + type Item = TokenTree; + type IntoIter = super::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.token_trees.into_iter() + } + } + + type LexError = String; + + /// Attempts to break the string into tokens and parse those tokens into a token stream. + /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters + /// or characters not existing in the language. + /// All tokens in the parsed stream get `Span::call_site()` spans. + /// + /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to + /// change these errors into `LexError`s later. + impl FromStr for TokenStream { + type Err = LexError; + + fn from_str(src: &str) -> Result { + let (subtree, _token_map) = + mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?; + + let subtree = subtree_replace_token_ids_with_unspecified(subtree); + Ok(TokenStream::with_subtree(subtree)) + } + } + + impl ToString for TokenStream { + fn to_string(&self) -> String { + tt::pretty(&self.token_trees) + } + } + + fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree { + tt::Subtree { + delimiter: subtree + .delimiter + .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }), + token_trees: subtree + .token_trees + .into_iter() + .map(token_tree_replace_token_ids_with_unspecified) + .collect(), + } + } + + fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree { + match tt { + tt::TokenTree::Leaf(leaf) => { + tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf)) + } + tt::TokenTree::Subtree(subtree) => { + tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree)) + } + } + } + + fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf { + match leaf { + tt::Leaf::Literal(lit) => { + tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit }) + } + tt::Leaf::Punct(punct) => { + tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct }) + } + tt::Leaf::Ident(ident) => { + tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident }) + } + } + } +} + +impl TokenStreamBuilder { + fn new() -> TokenStreamBuilder { + TokenStreamBuilder { acc: TokenStream::new() } + } + + fn push(&mut self, stream: TokenStream) { + self.acc.extend(stream.into_iter()) + } + + fn build(self) -> TokenStream { + self.acc + } +} + +pub struct FreeFunctions; + +#[derive(Clone)] +pub struct TokenStreamIter { + trees: IntoIter, +} + +#[derive(Default)] +pub struct Rustc { + ident_interner: IdentInterner, + // FIXME: store span information here. +} + +impl server::Types for Rustc { + type FreeFunctions = FreeFunctions; + type TokenStream = TokenStream; + type TokenStreamBuilder = TokenStreamBuilder; + type TokenStreamIter = TokenStreamIter; + type Group = Group; + type Punct = Punct; + type Ident = IdentId; + type Literal = Literal; + type SourceFile = SourceFile; + type Diagnostic = Diagnostic; + type Span = Span; + type MultiSpan = Vec; +} + +impl server::FreeFunctions for Rustc { + fn track_env_var(&mut self, _var: &str, _value: Option<&str>) { + // FIXME: track env var accesses + // https://github.com/rust-lang/rust/pull/71858 + } + fn track_path(&mut self, _path: &str) {} +} + +impl server::TokenStream for Rustc { + fn new(&mut self) -> Self::TokenStream { + Self::TokenStream::new() + } + + fn is_empty(&mut self, stream: &Self::TokenStream) -> bool { + stream.is_empty() + } + fn from_str(&mut self, src: &str) -> Self::TokenStream { + use std::str::FromStr; + + Self::TokenStream::from_str(src).expect("cannot parse string") + } + fn to_string(&mut self, stream: &Self::TokenStream) -> String { + stream.to_string() + } + fn from_token_tree( + &mut self, + tree: bridge::TokenTree, + ) -> Self::TokenStream { + match tree { + bridge::TokenTree::Group(group) => { + let tree = TokenTree::from(group); + Self::TokenStream::from_iter(vec![tree]) + } + + bridge::TokenTree::Ident(IdentId(index)) => { + let IdentData(ident) = self.ident_interner.get(index).clone(); + let ident: tt::Ident = ident; + let leaf = tt::Leaf::from(ident); + let tree = TokenTree::from(leaf); + Self::TokenStream::from_iter(vec![tree]) + } + + bridge::TokenTree::Literal(literal) => { + let leaf = tt::Leaf::from(literal); + let tree = TokenTree::from(leaf); + Self::TokenStream::from_iter(vec![tree]) + } + + bridge::TokenTree::Punct(p) => { + let leaf = tt::Leaf::from(p); + let tree = TokenTree::from(leaf); + Self::TokenStream::from_iter(vec![tree]) + } + } + } + + fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter { + let trees: Vec = stream.into_iter().collect(); + TokenStreamIter { trees: trees.into_iter() } + } + + fn expand_expr(&mut self, self_: &Self::TokenStream) -> Result { + Ok(self_.clone()) + } +} + +impl server::TokenStreamBuilder for Rustc { + fn new(&mut self) -> Self::TokenStreamBuilder { + Self::TokenStreamBuilder::new() + } + fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) { + builder.push(stream) + } + fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream { + builder.build() + } +} + +impl server::TokenStreamIter for Rustc { + fn next( + &mut self, + iter: &mut Self::TokenStreamIter, + ) -> Option> { + iter.trees.next().map(|tree| match tree { + TokenTree::Subtree(group) => bridge::TokenTree::Group(group), + TokenTree::Leaf(tt::Leaf::Ident(ident)) => { + bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident)))) + } + TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal), + TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct), + }) + } +} + +fn delim_to_internal(d: bridge::Delimiter) -> Option { + let kind = match d { + bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis, + bridge::Delimiter::Brace => tt::DelimiterKind::Brace, + bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket, + bridge::Delimiter::None => return None, + }; + Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind }) +} + +fn delim_to_external(d: Option) -> bridge::Delimiter { + match d.map(|it| it.kind) { + Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis, + Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace, + Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket, + None => bridge::Delimiter::None, + } +} + +fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing { + match spacing { + bridge::Spacing::Alone => Spacing::Alone, + bridge::Spacing::Joint => Spacing::Joint, + } +} + +fn spacing_to_external(spacing: Spacing) -> bridge::Spacing { + match spacing { + Spacing::Alone => bridge::Spacing::Alone, + Spacing::Joint => bridge::Spacing::Joint, + } +} + +impl server::Group for Rustc { + fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group { + Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees } + } + fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { + delim_to_external(group.delimiter) + } + + // NOTE: Return value of do not include delimiter + fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { + TokenStream { token_trees: group.token_trees.clone() } + } + + fn span(&mut self, group: &Self::Group) -> Self::Span { + group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) + } + + fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) { + if let Some(delim) = &mut group.delimiter { + delim.id = span; + } + } + + fn span_open(&mut self, group: &Self::Group) -> Self::Span { + // FIXME we only store one `TokenId` for the delimiters + group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) + } + + fn span_close(&mut self, group: &Self::Group) -> Self::Span { + // FIXME we only store one `TokenId` for the delimiters + group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) + } +} + +impl server::Punct for Rustc { + fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct { + tt::Punct { + char: ch, + spacing: spacing_to_internal(spacing), + id: tt::TokenId::unspecified(), + } + } + fn as_char(&mut self, punct: Self::Punct) -> char { + punct.char + } + fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing { + spacing_to_external(punct.spacing) + } + fn span(&mut self, punct: Self::Punct) -> Self::Span { + punct.id + } + fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct { + tt::Punct { id: span, ..punct } + } +} + +impl server::Ident for Rustc { + fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident { + IdentId(self.ident_interner.intern(&IdentData(tt::Ident { text: string.into(), id: span }))) + } + + fn span(&mut self, ident: Self::Ident) -> Self::Span { + self.ident_interner.get(ident.0).0.id + } + fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident { + let data = self.ident_interner.get(ident.0); + let new = IdentData(tt::Ident { id: span, ..data.0.clone() }); + IdentId(self.ident_interner.intern(&new)) + } +} + +impl server::Literal for Rustc { + fn debug_kind(&mut self, _literal: &Self::Literal) -> String { + // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these. + // They must still be present to be ABI-compatible and work with upstream proc_macro. + "".to_owned() + } + fn from_str(&mut self, s: &str) -> Result { + Ok(Literal { text: s.into(), id: tt::TokenId::unspecified() }) + } + fn symbol(&mut self, literal: &Self::Literal) -> String { + literal.text.to_string() + } + fn suffix(&mut self, _literal: &Self::Literal) -> Option { + None + } + + fn to_string(&mut self, literal: &Self::Literal) -> String { + literal.to_string() + } + + fn integer(&mut self, n: &str) -> Self::Literal { + let n = match n.parse::() { + Ok(n) => n.to_string(), + Err(_) => n.parse::().unwrap().to_string(), + }; + Literal { text: n.into(), id: tt::TokenId::unspecified() } + } + + fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal { + macro_rules! def_suffixed_integer { + ($kind:ident, $($ty:ty),*) => { + match $kind { + $( + stringify!($ty) => { + let n: $ty = n.parse().unwrap(); + format!(concat!("{}", stringify!($ty)), n) + } + )* + _ => unimplemented!("unknown args for typed_integer: n {}, kind {}", n, $kind), + } + } + } + + let text = def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize}; + + Literal { text: text.into(), id: tt::TokenId::unspecified() } + } + + fn float(&mut self, n: &str) -> Self::Literal { + let n: f64 = n.parse().unwrap(); + let mut text = f64::to_string(&n); + if !text.contains('.') { + text += ".0" + } + Literal { text: text.into(), id: tt::TokenId::unspecified() } + } + + fn f32(&mut self, n: &str) -> Self::Literal { + let n: f32 = n.parse().unwrap(); + let text = format!("{}f32", n); + Literal { text: text.into(), id: tt::TokenId::unspecified() } + } + + fn f64(&mut self, n: &str) -> Self::Literal { + let n: f64 = n.parse().unwrap(); + let text = format!("{}f64", n); + Literal { text: text.into(), id: tt::TokenId::unspecified() } + } + + fn string(&mut self, string: &str) -> Self::Literal { + let mut escaped = String::new(); + for ch in string.chars() { + escaped.extend(ch.escape_debug()); + } + Literal { text: format!("\"{}\"", escaped).into(), id: tt::TokenId::unspecified() } + } + + fn character(&mut self, ch: char) -> Self::Literal { + Literal { text: format!("'{}'", ch).into(), id: tt::TokenId::unspecified() } + } + + fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal { + let string = bytes + .iter() + .cloned() + .flat_map(ascii::escape_default) + .map(Into::::into) + .collect::(); + + Literal { text: format!("b\"{}\"", string).into(), id: tt::TokenId::unspecified() } + } + + fn span(&mut self, literal: &Self::Literal) -> Self::Span { + literal.id + } + + fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) { + literal.id = span; + } + + fn subspan( + &mut self, + _literal: &Self::Literal, + _start: Bound, + _end: Bound, + ) -> Option { + // FIXME handle span + None + } +} + +impl server::SourceFile for Rustc { + // FIXME these are all stubs + fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool { + true + } + fn path(&mut self, _file: &Self::SourceFile) -> String { + String::new() + } + fn is_real(&mut self, _file: &Self::SourceFile) -> bool { + true + } +} + +impl server::Diagnostic for Rustc { + fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic { + let mut diag = Diagnostic::new(level, msg); + diag.spans = spans; + diag + } + + fn sub( + &mut self, + _diag: &mut Self::Diagnostic, + _level: Level, + _msg: &str, + _spans: Self::MultiSpan, + ) { + // FIXME handle diagnostic + // + } + + fn emit(&mut self, _diag: Self::Diagnostic) { + // FIXME handle diagnostic + // diag.emit() + } +} + +impl server::Span for Rustc { + fn debug(&mut self, span: Self::Span) -> String { + format!("{:?}", span.0) + } + fn def_site(&mut self) -> Self::Span { + // MySpan(self.span_interner.intern(&MySpanData(Span::def_site()))) + // FIXME handle span + tt::TokenId::unspecified() + } + fn call_site(&mut self) -> Self::Span { + // MySpan(self.span_interner.intern(&MySpanData(Span::call_site()))) + // FIXME handle span + tt::TokenId::unspecified() + } + fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile { + SourceFile {} + } + fn save_span(&mut self, _span: Self::Span) -> usize { + // FIXME stub + 0 + } + fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span { + // FIXME stub + tt::TokenId::unspecified() + } + /// Recent feature, not yet in the proc_macro + /// + /// See PR: + /// https://github.com/rust-lang/rust/pull/55780 + fn source_text(&mut self, _span: Self::Span) -> Option { + None + } + + fn parent(&mut self, _span: Self::Span) -> Option { + // FIXME handle span + None + } + fn source(&mut self, span: Self::Span) -> Self::Span { + // FIXME handle span + span + } + fn start(&mut self, _span: Self::Span) -> LineColumn { + // FIXME handle span + LineColumn { line: 0, column: 0 } + } + fn end(&mut self, _span: Self::Span) -> LineColumn { + // FIXME handle span + LineColumn { line: 0, column: 0 } + } + fn join(&mut self, first: Self::Span, _second: Self::Span) -> Option { + // Just return the first span again, because some macros will unwrap the result. + Some(first) + } + fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span { + // FIXME handle span + tt::TokenId::unspecified() + } + + fn mixed_site(&mut self) -> Self::Span { + // FIXME handle span + tt::TokenId::unspecified() + } + + fn after(&mut self, _self_: Self::Span) -> Self::Span { + tt::TokenId::unspecified() + } + + fn before(&mut self, _self_: Self::Span) -> Self::Span { + tt::TokenId::unspecified() + } +} + +impl server::MultiSpan for Rustc { + fn new(&mut self) -> Self::MultiSpan { + // FIXME handle span + vec![] + } + + fn push(&mut self, other: &mut Self::MultiSpan, span: Self::Span) { + //TODP + other.push(span) + } +} + +#[cfg(test)] +mod tests { + use super::super::proc_macro::bridge::server::Literal; + use super::*; + + #[test] + fn test_rustc_server_literals() { + let mut srv = Rustc { ident_interner: IdentInterner::default() }; + assert_eq!(srv.integer("1234").text, "1234"); + + assert_eq!(srv.typed_integer("12", "u8").text, "12u8"); + assert_eq!(srv.typed_integer("255", "u16").text, "255u16"); + assert_eq!(srv.typed_integer("1234", "u32").text, "1234u32"); + assert_eq!(srv.typed_integer("15846685", "u64").text, "15846685u64"); + assert_eq!(srv.typed_integer("15846685258", "u128").text, "15846685258u128"); + assert_eq!(srv.typed_integer("156788984", "usize").text, "156788984usize"); + assert_eq!(srv.typed_integer("127", "i8").text, "127i8"); + assert_eq!(srv.typed_integer("255", "i16").text, "255i16"); + assert_eq!(srv.typed_integer("1234", "i32").text, "1234i32"); + assert_eq!(srv.typed_integer("15846685", "i64").text, "15846685i64"); + assert_eq!(srv.typed_integer("15846685258", "i128").text, "15846685258i128"); + assert_eq!(srv.float("0").text, "0.0"); + assert_eq!(srv.float("15684.5867").text, "15684.5867"); + assert_eq!(srv.f32("15684.58").text, "15684.58f32"); + assert_eq!(srv.f64("15684.58").text, "15684.58f64"); + + assert_eq!(srv.string("hello_world").text, "\"hello_world\""); + assert_eq!(srv.character('c').text, "'c'"); + assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\""); + + // u128::max + assert_eq!( + srv.integer("340282366920938463463374607431768211455").text, + "340282366920938463463374607431768211455" + ); + // i128::min + assert_eq!( + srv.integer("-170141183460469231731687303715884105728").text, + "-170141183460469231731687303715884105728" + ); + } + + #[test] + fn test_rustc_server_to_string() { + let s = TokenStream { + token_trees: vec![ + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + text: "struct".into(), + id: tt::TokenId::unspecified(), + })), + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + text: "T".into(), + id: tt::TokenId::unspecified(), + })), + tt::TokenTree::Subtree(tt::Subtree { + delimiter: Some(tt::Delimiter { + id: tt::TokenId::unspecified(), + kind: tt::DelimiterKind::Brace, + }), + token_trees: vec![], + }), + ], + }; + + assert_eq!(s.to_string(), "struct T {}"); + } + + #[test] + fn test_rustc_server_from_str() { + use std::str::FromStr; + let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree { + delimiter: Some(tt::Delimiter { + id: tt::TokenId::unspecified(), + kind: tt::DelimiterKind::Parenthesis, + }), + token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + text: "a".into(), + id: tt::TokenId::unspecified(), + }))], + }); + + let t1 = TokenStream::from_str("(a)").unwrap(); + assert_eq!(t1.token_trees.len(), 1); + assert_eq!(t1.token_trees[0], subtree_paren_a); + + let t2 = TokenStream::from_str("(a);").unwrap(); + assert_eq!(t2.token_trees.len(), 2); + assert_eq!(t2.token_trees[0], subtree_paren_a); + + let underscore = TokenStream::from_str("_").unwrap(); + assert_eq!( + underscore.token_trees[0], + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + text: "_".into(), + id: tt::TokenId::unspecified(), + })) + ); + } +} diff --git a/crates/proc-macro-srv/src/abis/mod.rs b/crates/proc-macro-srv/src/abis/mod.rs index 815f2e963803..c5a8db28deb7 100644 --- a/crates/proc-macro-srv/src/abis/mod.rs +++ b/crates/proc-macro-srv/src/abis/mod.rs @@ -30,6 +30,7 @@ mod abi_1_56; mod abi_1_57; mod abi_1_58; mod abi_1_63; +mod abi_internal; use super::dylib::LoadProcMacroDylibError; pub(crate) use abi_1_48::Abi as Abi_1_48; @@ -38,6 +39,7 @@ pub(crate) use abi_1_56::Abi as Abi_1_56; pub(crate) use abi_1_57::Abi as Abi_1_57; pub(crate) use abi_1_58::Abi as Abi_1_58; pub(crate) use abi_1_63::Abi as Abi_1_63; +pub(crate) use abi_internal::Abi as Abi_Internal; use libloading::Library; use proc_macro_api::{ProcMacroKind, RustCInfo}; diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index 52693547e596..5472b721cd60 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -10,6 +10,9 @@ //! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable` //! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)… #![allow(unreachable_pub)] +#![feature(proc_macro_internals)] +#![feature(proc_macro_diagnostic)] +#![feature(proc_macro_span)] mod dylib; mod abis; From 3a55f9cb01ceacab18de1832ab585df457be238f Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:27:54 +0200 Subject: [PATCH 2/8] Remove def_site / call_site / mixed_site, which moved somewhere else --- .../src/abis/abi_internal/rustc_server.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs index 5c596bc0e62a..4b0aab8cc3d1 100644 --- a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -638,16 +638,6 @@ impl server::Span for Rustc { fn debug(&mut self, span: Self::Span) -> String { format!("{:?}", span.0) } - fn def_site(&mut self) -> Self::Span { - // MySpan(self.span_interner.intern(&MySpanData(Span::def_site()))) - // FIXME handle span - tt::TokenId::unspecified() - } - fn call_site(&mut self) -> Self::Span { - // MySpan(self.span_interner.intern(&MySpanData(Span::call_site()))) - // FIXME handle span - tt::TokenId::unspecified() - } fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile { SourceFile {} } @@ -692,11 +682,6 @@ impl server::Span for Rustc { tt::TokenId::unspecified() } - fn mixed_site(&mut self) -> Self::Span { - // FIXME handle span - tt::TokenId::unspecified() - } - fn after(&mut self, _self_: Self::Span) -> Self::Span { tt::TokenId::unspecified() } From bc48abdceacebb1d0b7faac1e40ce8f6ff796490 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:37:19 +0200 Subject: [PATCH 3/8] Use proper import path for proc_macro::{Delimiter,Spacing}, remove some deprecated server interfaces --- .../src/abis/abi_internal/rustc_server.rs | 134 +++--------------- rust-toolchain.toml | 3 + 2 files changed, 23 insertions(+), 114 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs index 4b0aab8cc3d1..bce77f5023dd 100644 --- a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -8,7 +8,10 @@ //! //! FIXME: No span and source file information is implemented yet -use super::proc_macro::bridge::{self, server}; +use super::proc_macro::{ + self, + bridge::{self, server}, +}; use std::collections::HashMap; use std::hash::Hash; @@ -276,10 +279,6 @@ pub struct Rustc { impl server::Types for Rustc { type FreeFunctions = FreeFunctions; type TokenStream = TokenStream; - type TokenStreamBuilder = TokenStreamBuilder; - type TokenStreamIter = TokenStreamIter; - type Group = Group; - type Punct = Punct; type Ident = IdentId; type Literal = Literal; type SourceFile = SourceFile; @@ -297,10 +296,6 @@ impl server::FreeFunctions for Rustc { } impl server::TokenStream for Rustc { - fn new(&mut self) -> Self::TokenStream { - Self::TokenStream::new() - } - fn is_empty(&mut self, stream: &Self::TokenStream) -> bool { stream.is_empty() } @@ -344,130 +339,41 @@ impl server::TokenStream for Rustc { } } - fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter { - let trees: Vec = stream.into_iter().collect(); - TokenStreamIter { trees: trees.into_iter() } - } - fn expand_expr(&mut self, self_: &Self::TokenStream) -> Result { Ok(self_.clone()) } } -impl server::TokenStreamBuilder for Rustc { - fn new(&mut self) -> Self::TokenStreamBuilder { - Self::TokenStreamBuilder::new() - } - fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) { - builder.push(stream) - } - fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream { - builder.build() - } -} - -impl server::TokenStreamIter for Rustc { - fn next( - &mut self, - iter: &mut Self::TokenStreamIter, - ) -> Option> { - iter.trees.next().map(|tree| match tree { - TokenTree::Subtree(group) => bridge::TokenTree::Group(group), - TokenTree::Leaf(tt::Leaf::Ident(ident)) => { - bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident)))) - } - TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal), - TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct), - }) - } -} - -fn delim_to_internal(d: bridge::Delimiter) -> Option { +fn delim_to_internal(d: proc_macro::Delimiter) -> Option { let kind = match d { - bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis, - bridge::Delimiter::Brace => tt::DelimiterKind::Brace, - bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket, - bridge::Delimiter::None => return None, + proc_macro::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis, + proc_macro::Delimiter::Brace => tt::DelimiterKind::Brace, + proc_macro::Delimiter::Bracket => tt::DelimiterKind::Bracket, + proc_macro::Delimiter::None => return None, }; Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind }) } -fn delim_to_external(d: Option) -> bridge::Delimiter { +fn delim_to_external(d: Option) -> proc_macro::Delimiter { match d.map(|it| it.kind) { - Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis, - Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace, - Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket, - None => bridge::Delimiter::None, + Some(tt::DelimiterKind::Parenthesis) => proc_macro::Delimiter::Parenthesis, + Some(tt::DelimiterKind::Brace) => proc_macro::Delimiter::Brace, + Some(tt::DelimiterKind::Bracket) => proc_macro::Delimiter::Bracket, + None => proc_macro::Delimiter::None, } } -fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing { +fn spacing_to_internal(spacing: proc_macro::Spacing) -> Spacing { match spacing { - bridge::Spacing::Alone => Spacing::Alone, - bridge::Spacing::Joint => Spacing::Joint, + proc_macro::Spacing::Alone => Spacing::Alone, + proc_macro::Spacing::Joint => Spacing::Joint, } } -fn spacing_to_external(spacing: Spacing) -> bridge::Spacing { +fn spacing_to_external(spacing: Spacing) -> proc_macro::Spacing { match spacing { - Spacing::Alone => bridge::Spacing::Alone, - Spacing::Joint => bridge::Spacing::Joint, - } -} - -impl server::Group for Rustc { - fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group { - Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees } - } - fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { - delim_to_external(group.delimiter) - } - - // NOTE: Return value of do not include delimiter - fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { - TokenStream { token_trees: group.token_trees.clone() } - } - - fn span(&mut self, group: &Self::Group) -> Self::Span { - group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) - } - - fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) { - if let Some(delim) = &mut group.delimiter { - delim.id = span; - } - } - - fn span_open(&mut self, group: &Self::Group) -> Self::Span { - // FIXME we only store one `TokenId` for the delimiters - group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) - } - - fn span_close(&mut self, group: &Self::Group) -> Self::Span { - // FIXME we only store one `TokenId` for the delimiters - group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) - } -} - -impl server::Punct for Rustc { - fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct { - tt::Punct { - char: ch, - spacing: spacing_to_internal(spacing), - id: tt::TokenId::unspecified(), - } - } - fn as_char(&mut self, punct: Self::Punct) -> char { - punct.char - } - fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing { - spacing_to_external(punct.spacing) - } - fn span(&mut self, punct: Self::Punct) -> Self::Span { - punct.id - } - fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct { - tt::Punct { id: span, ..punct } + Spacing::Alone => proc_macro::Spacing::Alone, + Spacing::Joint => proc_macro::Spacing::Joint, } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000000..6908b6c8df70 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2022-07-18" +components = [ "rustfmt", "clippy", "rust-src" ] \ No newline at end of file From 267c94fc7994fde029bb377188efe2202eecf967 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:38:38 +0200 Subject: [PATCH 4/8] Add missing TokenStream methods --- .../src/abis/abi_internal/rustc_server.rs | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs index bce77f5023dd..4d89f8799873 100644 --- a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -309,7 +309,7 @@ impl server::TokenStream for Rustc { } fn from_token_tree( &mut self, - tree: bridge::TokenTree, + tree: bridge::TokenTree, ) -> Self::TokenStream { match tree { bridge::TokenTree::Group(group) => { @@ -342,6 +342,67 @@ impl server::TokenStream for Rustc { fn expand_expr(&mut self, self_: &Self::TokenStream) -> Result { Ok(self_.clone()) } + + fn concat_trees( + &mut self, + base: Option, + trees: Vec>, + ) -> Self::TokenStream { + let mut builder = TokenStreamBuilder::new(); + if let Some(base) = base { + builder.push(base); + } + for tree in trees { + builder.push(self.from_token_tree(tree)); + } + builder.build() + } + + fn concat_streams( + &mut self, + base: Option, + streams: Vec, + ) -> Self::TokenStream { + let mut builder = TokenStreamBuilder::new(); + if let Some(base) = base { + builder.push(base); + } + for stream in streams { + builder.push(stream); + } + builder.build() + } + + fn into_trees( + &mut self, + stream: Self::TokenStream, + ) -> Vec> { + stream + .into_iter() + .map(|tree| match tree { + tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { + bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident)))) + } + tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => bridge::TokenTree::Literal(lit), + tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { + bridge::TokenTree::Punct(bridge::Punct { + ch: punct.char as _, + joint: punct.spacing == tt::Spacing::Joint, + span: punct.id, + }) + } + tt::TokenTree::Subtree(subtree) => bridge::TokenTree::Group(bridge::Group { + delimiter: delim_to_external(subtree.delimiter), + stream: Some(TokenStream { token_trees: subtree.token_trees }), + span: bridge::DelimSpan { + open: Span::unspecified(), + close: Span::unspecified(), + entire: Span::unspecified(), + }, + }), + }) + .collect() + } } fn delim_to_internal(d: proc_macro::Delimiter) -> Option { From d5d5d972ddc2cb62edb0cc8816fcff51e39a48d9 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:39:18 +0200 Subject: [PATCH 5/8] derive Default for TokenStream --- crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs index 4d89f8799873..10ba2ba2cc8d 100644 --- a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -26,7 +26,7 @@ type Spacing = tt::Spacing; type Literal = tt::Literal; type Span = tt::TokenId; -#[derive(Debug, Clone)] +#[derive(Debug, Default, Clone)] pub struct TokenStream { pub token_trees: Vec, } From 9eaff7135fd55b2e2462cc432966e287988a5716 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:41:02 +0200 Subject: [PATCH 6/8] Fix Group/Punct variants in TokenStream::into_trees impl --- .../src/abis/abi_internal/rustc_server.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs index 10ba2ba2cc8d..6c93142a0a60 100644 --- a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -313,7 +313,11 @@ impl server::TokenStream for Rustc { ) -> Self::TokenStream { match tree { bridge::TokenTree::Group(group) => { - let tree = TokenTree::from(group); + let subtree = tt::Subtree { + delimiter: delim_to_internal(group.delimiter), + token_trees: group.stream.unwrap_or_default().token_trees, + }; + let tree = TokenTree::from(subtree); Self::TokenStream::from_iter(vec![tree]) } @@ -332,6 +336,11 @@ impl server::TokenStream for Rustc { } bridge::TokenTree::Punct(p) => { + let p = tt::Punct { + spacing: if p.joint { tt::Spacing::Joint } else { tt::Spacing::Alone }, + char: p.ch as _, + id: p.span, + }; let leaf = tt::Leaf::from(p); let tree = TokenTree::from(leaf); Self::TokenStream::from_iter(vec![tree]) From de2ffcd336f8ce3af8ebe51692fe93ab3b6e88de Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:42:56 +0200 Subject: [PATCH 7/8] impl Server for Rustc --- .../src/abis/abi_internal/rustc_server.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs index 6c93142a0a60..c9a26316755e 100644 --- a/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs +++ b/crates/proc-macro-srv/src/abis/abi_internal/rustc_server.rs @@ -679,6 +679,16 @@ impl server::MultiSpan for Rustc { } } +impl server::Server for Rustc { + fn globals(&mut self) -> bridge::ExpnGlobals { + bridge::ExpnGlobals { + def_site: tt::TokenId::unspecified(), + call_site: tt::TokenId::unspecified(), + mixed_site: tt::TokenId::unspecified(), + } + } +} + #[cfg(test)] mod tests { use super::super::proc_macro::bridge::server::Literal; From 8f83ca3459aa9d077b3d18881f81e06110b3af22 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Mon, 18 Jul 2022 14:44:37 +0200 Subject: [PATCH 8/8] Only ever use internal abi --- crates/proc-macro-srv/src/abis/mod.rs | 64 +++++++++++++++------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/crates/proc-macro-srv/src/abis/mod.rs b/crates/proc-macro-srv/src/abis/mod.rs index c5a8db28deb7..61e15fb9f4cf 100644 --- a/crates/proc-macro-srv/src/abis/mod.rs +++ b/crates/proc-macro-srv/src/abis/mod.rs @@ -60,6 +60,7 @@ pub(crate) enum Abi { Abi1_57(Abi_1_57), Abi1_58(Abi_1_58), Abi1_63(Abi_1_63), + AbiInternal(Abi_Internal), } impl Abi { @@ -75,37 +76,42 @@ impl Abi { pub fn from_lib( lib: &Library, symbol_name: String, - info: RustCInfo, + _info: RustCInfo, ) -> Result { + { + let inner = unsafe { Abi_Internal::from_lib(lib, symbol_name) }?; + Ok(Abi::AbiInternal(inner)) + } + // FIXME: this should use exclusive ranges when they're stable // https://github.com/rust-lang/rust/issues/37854 - match (info.version.0, info.version.1) { - (1, 48..=53) => { - let inner = unsafe { Abi_1_48::from_lib(lib, symbol_name) }?; - Ok(Abi::Abi1_48(inner)) - } - (1, 54..=55) => { - let inner = unsafe { Abi_1_54::from_lib(lib, symbol_name) }?; - Ok(Abi::Abi1_54(inner)) - } - (1, 56) => { - let inner = unsafe { Abi_1_56::from_lib(lib, symbol_name) }?; - Ok(Abi::Abi1_56(inner)) - } - (1, 57) => { - let inner = unsafe { Abi_1_57::from_lib(lib, symbol_name) }?; - Ok(Abi::Abi1_57(inner)) - } - (1, 58..=62) => { - let inner = unsafe { Abi_1_58::from_lib(lib, symbol_name) }?; - Ok(Abi::Abi1_58(inner)) - } - (1, 63..) => { - let inner = unsafe { Abi_1_63::from_lib(lib, symbol_name) }?; - Ok(Abi::Abi1_63(inner)) - } - _ => Err(LoadProcMacroDylibError::UnsupportedABI), - } + // match (info.version.0, info.version.1) { + // (1, 48..=53) => { + // let inner = unsafe { Abi_1_48::from_lib(lib, symbol_name) }?; + // Ok(Abi::Abi1_48(inner)) + // } + // (1, 54..=55) => { + // let inner = unsafe { Abi_1_54::from_lib(lib, symbol_name) }?; + // Ok(Abi::Abi1_54(inner)) + // } + // (1, 56) => { + // let inner = unsafe { Abi_1_56::from_lib(lib, symbol_name) }?; + // Ok(Abi::Abi1_56(inner)) + // } + // (1, 57) => { + // let inner = unsafe { Abi_1_57::from_lib(lib, symbol_name) }?; + // Ok(Abi::Abi1_57(inner)) + // } + // (1, 58..=62) => { + // let inner = unsafe { Abi_1_58::from_lib(lib, symbol_name) }?; + // Ok(Abi::Abi1_58(inner)) + // } + // (1, 63..) => { + // let inner = unsafe { Abi_1_63::from_lib(lib, symbol_name) }?; + // Ok(Abi::Abi1_63(inner)) + // } + // _ => Err(LoadProcMacroDylibError::UnsupportedABI), + // } } pub fn expand( @@ -121,6 +127,7 @@ impl Abi { Self::Abi1_57(abi) => abi.expand(macro_name, macro_body, attributes), Self::Abi1_58(abi) => abi.expand(macro_name, macro_body, attributes), Self::Abi1_63(abi) => abi.expand(macro_name, macro_body, attributes), + Self::AbiInternal(abi) => abi.expand(macro_name, macro_body, attributes), } } @@ -132,6 +139,7 @@ impl Abi { Self::Abi1_57(abi) => abi.list_macros(), Self::Abi1_58(abi) => abi.list_macros(), Self::Abi1_63(abi) => abi.list_macros(), + Self::AbiInternal(abi) => abi.list_macros(), } } }