Skip to content

Commit a64c120

Browse files
committed
Auto merge of rust-lang#12492 - bjorn3:proc_macro_abi_1_63, r=lnicola
feat: Add proc macro ABI for rustc 1.63 Fixes rust-lang/rust-analyzer#12489 This bumps the MSRV to 1.61 due to usage of function pointers and `impl Trait` in const functions. <details> <summary>Diff from upstream proc_macro as of rust-lang/rust@e45d997 (misses lib.rs as it got renamed to mod.rs)</summary> ```diff diff -u --recursive ../rust/library/proc_macro/src/bridge/client.rs crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/bridge/client.rs --- ../rust/library/proc_macro/src/bridge/client.rs 2022-06-08 13:14:57.763123238 +0000 +++ crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/bridge/client.rs 2022-06-08 13:33:23.378430287 +0000 `@@` -430,27 +430,27 `@@` buf } -impl Client<crate::TokenStream, crate::TokenStream> { - pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self { +impl Client<super::super::TokenStream, super::super::TokenStream> { + pub const fn expand1(f: impl Fn(super::super::TokenStream) -> super::super::TokenStream + Copy) -> Self { Client { get_handle_counters: HandleCounters::get, run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { - run_client(bridge, |input| f(crate::TokenStream(input)).0) + run_client(bridge, |input| f(super::super::TokenStream(input)).0) }), _marker: PhantomData, } } } -impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> { +impl Client<(super::super::TokenStream, super::super::TokenStream), super::super::TokenStream> { pub const fn expand2( - f: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy, + f: impl Fn(super::super::TokenStream, super::super::TokenStream) -> super::super::TokenStream + Copy, ) -> Self { Client { get_handle_counters: HandleCounters::get, run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { run_client(bridge, |(input, input2)| { - f(crate::TokenStream(input), crate::TokenStream(input2)).0 + f(super::super::TokenStream(input), super::super::TokenStream(input2)).0 }) }), _marker: PhantomData, `@@` -464,17 +464,17 `@@` CustomDerive { trait_name: &'static str, attributes: &'static [&'static str], - client: Client<crate::TokenStream, crate::TokenStream>, + client: Client<super::super::TokenStream, super::super::TokenStream>, }, Attr { name: &'static str, - client: Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream>, + client: Client<(super::super::TokenStream, super::super::TokenStream), super::super::TokenStream>, }, Bang { name: &'static str, - client: Client<crate::TokenStream, crate::TokenStream>, + client: Client<super::super::TokenStream, super::super::TokenStream>, }, } `@@` -490,21 +490,21 `@@` pub const fn custom_derive( trait_name: &'static str, attributes: &'static [&'static str], - expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy, + expand: impl Fn(super::super::TokenStream) -> super::super::TokenStream + Copy, ) -> Self { ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) } } pub const fn attr( name: &'static str, - expand: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy, + expand: impl Fn(super::super::TokenStream, super::super::TokenStream) -> super::super::TokenStream + Copy, ) -> Self { ProcMacro::Attr { name, client: Client::expand2(expand) } } pub const fn bang( name: &'static str, - expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy, + expand: impl Fn(super::super::TokenStream) -> super::super::TokenStream + Copy, ) -> Self { ProcMacro::Bang { name, client: Client::expand1(expand) } } diff -u --recursive ../rust/library/proc_macro/src/bridge/mod.rs crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/bridge/mod.rs --- ../rust/library/proc_macro/src/bridge/mod.rs 2022-06-08 13:14:57.763123238 +0000 +++ crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/bridge/mod.rs 2022-06-08 13:33:39.694243060 +0000 `@@` -8,7 +8,7 `@@` #![deny(unsafe_code)] -use crate::{Delimiter, Level, LineColumn, Spacing}; +pub use super::{Delimiter, Level, LineColumn, Spacing}; use std::fmt; use std::hash::Hash; use std::marker; diff '--color=always' -u --recursive ../rust/library/proc_macro/src/bridge/server.rs crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/bridge/server.rs --- ../rust/library/proc_macro/src/bridge/server.rs 2022-06-08 13:14:57.763123238 +0000 +++ crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/bridge/server.rs 2022-06-08 13:33:54.306075391 +0000 `@@` -274,7 +274,7 `@@` Result::decode(&mut &buf[..], &mut dispatcher.handle_store) } -impl client::Client<crate::TokenStream, crate::TokenStream> { +impl client::Client<super::super::TokenStream, super::super::TokenStream> { pub fn run<S: Server>( &self, strategy: &impl ExecutionStrategy, `@@` -295,7 +295,7 `@@` } } -impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> { +impl client::Client<(super::super::TokenStream, super::super::TokenStream), super::super::TokenStream> { pub fn run<S: Server>( &self, strategy: &impl ExecutionStrategy, diff -u --recursive ../rust/library/proc_macro/src/diagnostic.rs crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/diagnostic.rs --- ../rust/library/proc_macro/src/diagnostic.rs 2022-05-11 10:07:59.099909725 +0000 +++ crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/diagnostic.rs 2022-06-08 13:35:01.169308145 +0000 `@@` -1,7 +1,6 `@@` -use crate::Span; +use super::Span; /// An enum representing a diagnostic level. -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[derive(Copy, Clone, Debug)] #[non_exhaustive] pub enum Level { `@@` -16,27 +15,23 `@@` } /// Trait implemented by types that can be converted into a set of `Span`s. -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub trait MultiSpan { /// Converts `self` into a `Vec<Span>`. fn into_spans(self) -> Vec<Span>; } -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] impl MultiSpan for Span { fn into_spans(self) -> Vec<Span> { vec![self] } } -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] impl MultiSpan for Vec<Span> { fn into_spans(self) -> Vec<Span> { self } } -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] impl<'a> MultiSpan for &'a [Span] { fn into_spans(self) -> Vec<Span> { self.to_vec() `@@` -45,7 +40,6 `@@` /// A structure representing a diagnostic message and associated children /// messages. -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[derive(Clone, Debug)] pub struct Diagnostic { level: Level, `@@` -56,7 +50,6 `@@` macro_rules! diagnostic_child_methods { ($spanned:ident, $regular:ident, $level:expr) => { - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[doc = concat!("Adds a new child diagnostics message to `self` with the [`", stringify!($level), "`] level, and the given `spans` and `message`.")] pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic `@@` -68,7 +61,6 `@@` self } - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] #[doc = concat!("Adds a new child diagnostic message to `self` with the [`", stringify!($level), "`] level, and the given `message`.")] pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic { `@@` -80,10 +72,8 `@@` /// Iterator over the children diagnostics of a `Diagnostic`. #[derive(Debug, Clone)] -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub struct Children<'a>(std::slice::Iter<'a, Diagnostic>); -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] impl<'a> Iterator for Children<'a> { type Item = &'a Diagnostic; `@@` -92,17 +82,14 `@@` } } -#[unstable(feature = "proc_macro_diagnostic", issue = "54140")] impl Diagnostic { /// Creates a new diagnostic with the given `level` and `message`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic { Diagnostic { level, message: message.into(), spans: vec![], children: vec![] } } /// Creates a new diagnostic with the given `level` and `message` pointing to /// the given set of `spans`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic where S: MultiSpan, `@@` -117,59 +104,51 `@@` diagnostic_child_methods!(span_help, help, Level::Help); /// Returns the diagnostic `level` for `self`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn level(&self) -> Level { self.level } /// Sets the level in `self` to `level`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn set_level(&mut self, level: Level) { self.level = level; } /// Returns the message in `self`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn message(&self) -> &str { &self.message } /// Sets the message in `self` to `message`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn set_message<T: Into<String>>(&mut self, message: T) { self.message = message.into(); } /// Returns the `Span`s in `self`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn spans(&self) -> &[Span] { &self.spans } /// Sets the `Span`s in `self` to `spans`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn set_spans<S: MultiSpan>(&mut self, spans: S) { self.spans = spans.into_spans(); } /// Returns an iterator over the children diagnostics of `self`. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn children(&self) -> Children<'_> { Children(self.children.iter()) } /// Emit the diagnostic. - #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn emit(self) { - fn to_internal(spans: Vec<Span>) -> crate::bridge::client::MultiSpan { - let mut multi_span = crate::bridge::client::MultiSpan::new(); + fn to_internal(spans: Vec<Span>) -> super::bridge::client::MultiSpan { + let mut multi_span = super::bridge::client::MultiSpan::new(); for span in spans { multi_span.push(span.0); } multi_span } - let mut diag = crate::bridge::client::Diagnostic::new( + let mut diag = super::bridge::client::Diagnostic::new( self.level, &self.message[..], to_internal(self.spans), Only in ../rust/library/proc_macro/src/: lib.rs Only in crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/: mod.rs diff -u --recursive ../rust/library/proc_macro/src/quote.rs crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/quote.rs --- ../rust/library/proc_macro/src/quote.rs 2022-05-11 10:22:36.097429479 +0000 +++ crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/quote.rs 2022-06-08 13:35:08.737221303 +0000 `@@` -4,7 +4,7 `@@` //! This quasiquoter uses macros 2.0 hygiene to reliably access //! items from `proc_macro`, to build a `proc_macro::TokenStream`. -use crate::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use super::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; macro_rules! quote_tt { (($($t:tt)*)) => { Group::new(Delimiter::Parenthesis, quote!($($t)*)) }; `@@` -59,10 +59,9 `@@` /// This is the actual implementation of the `quote!()` proc macro. /// /// It is loaded by the compiler in `register_builtin_macros`. -#[unstable(feature = "proc_macro_quote", issue = "54722")] pub fn quote(stream: TokenStream) -> TokenStream { if stream.is_empty() { - return quote!(crate::TokenStream::new()); + return quote!(super::TokenStream::new()); } let proc_macro_crate = quote!(crate); let mut after_dollar = false; `@@` -73,7 +72,7 `@@` after_dollar = false; match tree { TokenTree::Ident(_) => { - return Some(quote!(Into::<crate::TokenStream>::into( + return Some(quote!(Into::<super::TokenStream>::into( Clone::clone(&(@ tree))),)); } TokenTree::Punct(ref tt) if tt.as_char() == '$' => {} `@@` -86,33 +85,33 `@@` } } - Some(quote!(crate::TokenStream::from((@ match tree { - TokenTree::Punct(tt) => quote!(crate::TokenTree::Punct(crate::Punct::new( + Some(quote!(super::TokenStream::from((@ match tree { + TokenTree::Punct(tt) => quote!(super::TokenTree::Punct(super::Punct::new( (@ TokenTree::from(Literal::character(tt.as_char()))), (@ match tt.spacing() { - Spacing::Alone => quote!(crate::Spacing::Alone), - Spacing::Joint => quote!(crate::Spacing::Joint), + Spacing::Alone => quote!(super::Spacing::Alone), + Spacing::Joint => quote!(super::Spacing::Joint), }), ))), - TokenTree::Group(tt) => quote!(crate::TokenTree::Group(crate::Group::new( + TokenTree::Group(tt) => quote!(super::TokenTree::Group(super::Group::new( (@ match tt.delimiter() { - Delimiter::Parenthesis => quote!(crate::Delimiter::Parenthesis), - Delimiter::Brace => quote!(crate::Delimiter::Brace), - Delimiter::Bracket => quote!(crate::Delimiter::Bracket), - Delimiter::None => quote!(crate::Delimiter::None), + Delimiter::Parenthesis => quote!(super::Delimiter::Parenthesis), + Delimiter::Brace => quote!(super::Delimiter::Brace), + Delimiter::Bracket => quote!(super::Delimiter::Bracket), + Delimiter::None => quote!(super::Delimiter::None), }), (@ quote(tt.stream())), ))), - TokenTree::Ident(tt) => quote!(crate::TokenTree::Ident(crate::Ident::new( + TokenTree::Ident(tt) => quote!(super::TokenTree::Ident(super::Ident::new( (@ TokenTree::from(Literal::string(&tt.to_string()))), (@ quote_span(proc_macro_crate.clone(), tt.span())), ))), - TokenTree::Literal(tt) => quote!(crate::TokenTree::Literal({ + TokenTree::Literal(tt) => quote!(super::TokenTree::Literal({ let mut iter = (@ TokenTree::from(Literal::string(&tt.to_string()))) - .parse::<crate::TokenStream>() + .parse::<super::TokenStream>() .unwrap() .into_iter(); - if let (Some(crate::TokenTree::Literal(mut lit)), None) = + if let (Some(super::TokenTree::Literal(mut lit)), None) = (iter.next(), iter.next()) { lit.set_span((@ quote_span(proc_macro_crate.clone(), tt.span()))); `@@` -129,12 +128,11 `@@` panic!("unexpected trailing `$` in `quote!`"); } - quote!([(@ tokens)].iter().cloned().collect::<crate::TokenStream>()) + quote!([(@ tokens)].iter().cloned().collect::<super::TokenStream>()) } /// Quote a `Span` into a `TokenStream`. /// This is needed to implement a custom quoter. -#[unstable(feature = "proc_macro_quote", issue = "54722")] pub fn quote_span(proc_macro_crate: TokenStream, span: Span) -> TokenStream { let id = span.save_span(); quote!((@ proc_macro_crate ) ::Span::recover_proc_macro_span((@ TokenTree::from(Literal::usize_unsuffixed(id))))) ``` </details>
2 parents 66a8421 + f9e1ff6 commit a64c120

File tree

15 files changed

+4293
-1
lines changed

15 files changed

+4293
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//! Macro ABI for version 1.63 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+
11+
use libloading::Library;
12+
use proc_macro_api::ProcMacroKind;
13+
14+
use super::PanicMessage;
15+
16+
pub(crate) struct Abi {
17+
exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
18+
}
19+
20+
impl From<proc_macro::bridge::PanicMessage> for PanicMessage {
21+
fn from(p: proc_macro::bridge::PanicMessage) -> Self {
22+
Self { message: p.as_str().map(|s| s.to_string()) }
23+
}
24+
}
25+
26+
impl Abi {
27+
pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> {
28+
let macros: libloading::Symbol<&&[proc_macro::bridge::client::ProcMacro]> =
29+
lib.get(symbol_name.as_bytes())?;
30+
Ok(Self { exported_macros: macros.to_vec() })
31+
}
32+
33+
pub fn expand(
34+
&self,
35+
macro_name: &str,
36+
macro_body: &tt::Subtree,
37+
attributes: Option<&tt::Subtree>,
38+
) -> Result<tt::Subtree, PanicMessage> {
39+
let parsed_body = rustc_server::TokenStream::with_subtree(macro_body.clone());
40+
41+
let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| {
42+
rustc_server::TokenStream::with_subtree(attr.clone())
43+
});
44+
45+
for proc_macro in &self.exported_macros {
46+
match proc_macro {
47+
proc_macro::bridge::client::ProcMacro::CustomDerive {
48+
trait_name, client, ..
49+
} if *trait_name == macro_name => {
50+
let res = client.run(
51+
&proc_macro::bridge::server::SameThread,
52+
rustc_server::Rustc::default(),
53+
parsed_body,
54+
true,
55+
);
56+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
57+
}
58+
proc_macro::bridge::client::ProcMacro::Bang { name, client }
59+
if *name == macro_name =>
60+
{
61+
let res = client.run(
62+
&proc_macro::bridge::server::SameThread,
63+
rustc_server::Rustc::default(),
64+
parsed_body,
65+
true,
66+
);
67+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
68+
}
69+
proc_macro::bridge::client::ProcMacro::Attr { name, client }
70+
if *name == macro_name =>
71+
{
72+
let res = client.run(
73+
&proc_macro::bridge::server::SameThread,
74+
rustc_server::Rustc::default(),
75+
parsed_attributes,
76+
parsed_body,
77+
true,
78+
);
79+
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
80+
}
81+
_ => continue,
82+
}
83+
}
84+
85+
Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
86+
}
87+
88+
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
89+
self.exported_macros
90+
.iter()
91+
.map(|proc_macro| match proc_macro {
92+
proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
93+
(trait_name.to_string(), ProcMacroKind::CustomDerive)
94+
}
95+
proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
96+
(name.to_string(), ProcMacroKind::FuncLike)
97+
}
98+
proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
99+
(name.to_string(), ProcMacroKind::Attr)
100+
}
101+
})
102+
.collect()
103+
}
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
//! Buffer management for same-process client<->server communication.
2+
3+
use std::io::{self, Write};
4+
use std::mem;
5+
use std::ops::{Deref, DerefMut};
6+
use std::slice;
7+
8+
#[repr(C)]
9+
pub struct Buffer {
10+
data: *mut u8,
11+
len: usize,
12+
capacity: usize,
13+
reserve: extern "C" fn(Buffer, usize) -> Buffer,
14+
drop: extern "C" fn(Buffer),
15+
}
16+
17+
unsafe impl Sync for Buffer {}
18+
unsafe impl Send for Buffer {}
19+
20+
impl Default for Buffer {
21+
#[inline]
22+
fn default() -> Self {
23+
Self::from(vec![])
24+
}
25+
}
26+
27+
impl Deref for Buffer {
28+
type Target = [u8];
29+
#[inline]
30+
fn deref(&self) -> &[u8] {
31+
unsafe { slice::from_raw_parts(self.data as *const u8, self.len) }
32+
}
33+
}
34+
35+
impl DerefMut for Buffer {
36+
#[inline]
37+
fn deref_mut(&mut self) -> &mut [u8] {
38+
unsafe { slice::from_raw_parts_mut(self.data, self.len) }
39+
}
40+
}
41+
42+
impl Buffer {
43+
#[inline]
44+
pub(super) fn new() -> Self {
45+
Self::default()
46+
}
47+
48+
#[inline]
49+
pub(super) fn clear(&mut self) {
50+
self.len = 0;
51+
}
52+
53+
#[inline]
54+
pub(super) fn take(&mut self) -> Self {
55+
mem::take(self)
56+
}
57+
58+
// We have the array method separate from extending from a slice. This is
59+
// because in the case of small arrays, codegen can be more efficient
60+
// (avoiding a memmove call). With extend_from_slice, LLVM at least
61+
// currently is not able to make that optimization.
62+
#[inline]
63+
pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[u8; N]) {
64+
if xs.len() > (self.capacity - self.len) {
65+
let b = self.take();
66+
*self = (b.reserve)(b, xs.len());
67+
}
68+
unsafe {
69+
xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
70+
self.len += xs.len();
71+
}
72+
}
73+
74+
#[inline]
75+
pub(super) fn extend_from_slice(&mut self, xs: &[u8]) {
76+
if xs.len() > (self.capacity - self.len) {
77+
let b = self.take();
78+
*self = (b.reserve)(b, xs.len());
79+
}
80+
unsafe {
81+
xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
82+
self.len += xs.len();
83+
}
84+
}
85+
86+
#[inline]
87+
pub(super) fn push(&mut self, v: u8) {
88+
// The code here is taken from Vec::push, and we know that reserve()
89+
// will panic if we're exceeding isize::MAX bytes and so there's no need
90+
// to check for overflow.
91+
if self.len == self.capacity {
92+
let b = self.take();
93+
*self = (b.reserve)(b, 1);
94+
}
95+
unsafe {
96+
*self.data.add(self.len) = v;
97+
self.len += 1;
98+
}
99+
}
100+
}
101+
102+
impl Write for Buffer {
103+
#[inline]
104+
fn write(&mut self, xs: &[u8]) -> io::Result<usize> {
105+
self.extend_from_slice(xs);
106+
Ok(xs.len())
107+
}
108+
109+
#[inline]
110+
fn write_all(&mut self, xs: &[u8]) -> io::Result<()> {
111+
self.extend_from_slice(xs);
112+
Ok(())
113+
}
114+
115+
#[inline]
116+
fn flush(&mut self) -> io::Result<()> {
117+
Ok(())
118+
}
119+
}
120+
121+
impl Drop for Buffer {
122+
#[inline]
123+
fn drop(&mut self) {
124+
let b = self.take();
125+
(b.drop)(b);
126+
}
127+
}
128+
129+
impl From<Vec<u8>> for Buffer {
130+
fn from(mut v: Vec<u8>) -> Self {
131+
let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity());
132+
mem::forget(v);
133+
134+
// This utility function is nested in here because it can *only*
135+
// be safely called on `Buffer`s created by *this* `proc_macro`.
136+
fn to_vec(b: Buffer) -> Vec<u8> {
137+
unsafe {
138+
let Buffer { data, len, capacity, .. } = b;
139+
mem::forget(b);
140+
Vec::from_raw_parts(data, len, capacity)
141+
}
142+
}
143+
144+
extern "C" fn reserve(b: Buffer, additional: usize) -> Buffer {
145+
let mut v = to_vec(b);
146+
v.reserve(additional);
147+
Buffer::from(v)
148+
}
149+
150+
extern "C" fn drop(b: Buffer) {
151+
mem::drop(to_vec(b));
152+
}
153+
154+
Buffer { data, len, capacity, reserve, drop }
155+
}
156+
}

0 commit comments

Comments
 (0)