diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 92558f2b7d9cc..2c2f0b8f3db23 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -5,6 +5,9 @@ use std::marker::PhantomData; use std::sync::atomic::AtomicU32; use super::*; +use crate::StandaloneLevel; +use crate::bridge::server::{Dispatcher, DispatcherTrait}; +use crate::bridge::standalone::NoRustc; macro_rules! define_client_handles { ( @@ -58,7 +61,7 @@ macro_rules! define_client_handles { } } - impl DecodeMut<'_, '_, S> for $oty { + impl Decode<'_, '_, S> for $oty { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { $oty { handle: handle::Handle::decode(r, s), @@ -82,7 +85,7 @@ macro_rules! define_client_handles { } } - impl DecodeMut<'_, '_, S> for $ity { + impl Decode<'_, '_, S> for $ity { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { $ity { handle: handle::Handle::decode(r, s), @@ -141,7 +144,10 @@ macro_rules! define_client_side { api_tags::Method::$name(api_tags::$name::$method).encode(&mut buf, &mut ()); $($arg.encode(&mut buf, &mut ());)* - buf = bridge.dispatch.call(buf); + buf = match &mut bridge.dispatch { + DispatchWay::Closure(f) => f.call(buf), + DispatchWay::Directly(disp) => disp.dispatch(buf), + }; let r = Result::<_, PanicMessage>::decode(&mut &buf[..], &mut ()); @@ -155,13 +161,18 @@ macro_rules! define_client_side { } with_api!(self, self, define_client_side); +enum DispatchWay<'a> { + Closure(closure::Closure<'a, Buffer, Buffer>), + Directly(Dispatcher), +} + struct Bridge<'a> { /// Reusable buffer (only `clear`-ed, never shrunk), primarily /// used for making requests. cached_buffer: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: DispatchWay<'a>, /// Provided globals for this macro expansion. globals: ExpnGlobals, @@ -173,12 +184,33 @@ impl<'a> !Sync for Bridge<'a> {} #[allow(unsafe_code)] mod state { use std::cell::{Cell, RefCell}; + use std::marker::PhantomData; use std::ptr; use super::Bridge; + use crate::StandaloneLevel; + use crate::bridge::buffer::Buffer; + use crate::bridge::client::{COUNTERS, DispatchWay}; + use crate::bridge::server::{Dispatcher, HandleStore, MarkedTypes}; + use crate::bridge::{ExpnGlobals, Marked, standalone}; thread_local! { static BRIDGE_STATE: Cell<*const ()> = const { Cell::new(ptr::null()) }; + static STANDALONE: RefCell> = RefCell::new(standalone_bridge()); + pub(super) static USE_STANDALONE: Cell = const { Cell::new(StandaloneLevel::Never) }; + } + + fn standalone_bridge() -> Bridge<'static> { + let mut store = HandleStore::new(&COUNTERS); + let id = store.Span.alloc(Marked { value: standalone::Span::DUMMY, _marker: PhantomData }); + let dummy = super::Span { handle: id }; + let dispatcher = + Dispatcher { handle_store: store, server: MarkedTypes(standalone::NoRustc) }; + Bridge { + cached_buffer: Buffer::new(), + dispatch: DispatchWay::Directly(dispatcher), + globals: ExpnGlobals { call_site: dummy, def_site: dummy, mixed_site: dummy }, + } } pub(super) fn set<'bridge, R>(state: &RefCell>, f: impl FnOnce() -> R) -> R { @@ -199,16 +231,23 @@ mod state { pub(super) fn with( f: impl for<'bridge> FnOnce(Option<&RefCell>>) -> R, ) -> R { - let state = BRIDGE_STATE.get(); - // SAFETY: the only place where the pointer is set is in `set`. It puts - // back the previous value after the inner call has returned, so we know - // that as long as the pointer is not null, it came from a reference to - // a `RefCell` that outlasts the call to this function. Since `f` - // works the same for any lifetime of the bridge, including the actual - // one, we can lie here and say that the lifetime is `'static` without - // anyone noticing. - let bridge = unsafe { state.cast::>>().as_ref() }; - f(bridge) + let level = USE_STANDALONE.get(); + if level == StandaloneLevel::Always + || (level == StandaloneLevel::FallbackOnly && BRIDGE_STATE.get().is_null()) + { + STANDALONE.with(|bridge| f(Some(bridge))) + } else { + let state = BRIDGE_STATE.get(); + // SAFETY: the only place where the pointer is set is in `set`. It puts + // back the previous value after the inner call has returned, so we know + // that as long as the pointer is not null, it came from a reference to + // a `RefCell` that outlasts the call to this function. Since `f` + // works the same for any lifetime of the bridge, including the actual + // one, we can lie here and say that the lifetime is `'static` without + // anyone noticing. + let bridge = unsafe { state.cast::>>().as_ref() }; + f(bridge) + } } } @@ -228,6 +267,10 @@ pub(crate) fn is_available() -> bool { state::with(|s| s.is_some()) } +pub(crate) fn enable_standalone(level: StandaloneLevel) { + state::USE_STANDALONE.set(level); +} + /// A client-side RPC entry-point, which may be using a different `proc_macro` /// from the one used by the server, but can be invoked compatibly. /// @@ -276,7 +319,7 @@ fn maybe_install_panic_hook(force_show_panics: bool) { /// Client-side helper for handling client panics, entering the bridge, /// deserializing input and serializing output. // FIXME(eddyb) maybe replace `Bridge::enter` with this? -fn run_client DecodeMut<'a, 's, ()>, R: Encode<()>>( +fn run_client Decode<'a, 's, ()>, R: Encode<()>>( config: BridgeConfig<'_>, f: impl FnOnce(A) -> R, ) -> Buffer { @@ -292,7 +335,11 @@ fn run_client DecodeMut<'a, 's, ()>, R: Encode<()>>( let (globals, input) = <(ExpnGlobals, A)>::decode(reader, &mut ()); // Put the buffer we used for input back in the `Bridge` for requests. - let state = RefCell::new(Bridge { cached_buffer: buf.take(), dispatch, globals }); + let state = RefCell::new(Bridge { + cached_buffer: buf.take(), + dispatch: DispatchWay::Closure(dispatch), + globals, + }); let output = state::set(&state, || f(input)); diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 582c43c78fcbb..4f5fe2a08b8b7 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -138,12 +138,13 @@ mod rpc; mod selfless_reify; #[forbid(unsafe_code)] pub mod server; +pub(crate) mod standalone; #[allow(unsafe_code)] mod symbol; use buffer::Buffer; pub use rpc::PanicMessage; -use rpc::{DecodeMut, Encode, Reader, Writer}; +use rpc::{Decode, Encode, Reader, Writer}; /// Configuration for establishing an active connection between a server and a /// client. The server creates the bridge config (`run_server` in `server.rs`), @@ -168,7 +169,7 @@ impl !Sync for BridgeConfig<'_> {} #[forbid(unsafe_code)] #[allow(non_camel_case_types)] mod api_tags { - use super::rpc::{DecodeMut, Encode, Reader, Writer}; + use super::rpc::{Decode, Encode, Reader, Writer}; macro_rules! declare_tags { ($($name:ident { diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 7f4f5fc3a97d5..ed67674a74ab7 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -12,7 +12,7 @@ pub(super) trait Encode: Sized { pub(super) type Reader<'a> = &'a [u8]; -pub(super) trait DecodeMut<'a, 's, S>: Sized { +pub(super) trait Decode<'a, 's, S>: Sized { fn decode(r: &mut Reader<'a>, s: &'s mut S) -> Self; } @@ -24,7 +24,7 @@ macro_rules! rpc_encode_decode { } } - impl DecodeMut<'_, '_, S> for $ty { + impl Decode<'_, '_, S> for $ty { fn decode(r: &mut Reader<'_>, _: &mut S) -> Self { const N: usize = size_of::<$ty>(); @@ -43,12 +43,12 @@ macro_rules! rpc_encode_decode { } } - impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S> + impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> for $name $(<$($T),+>)? { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { $name { - $($field: DecodeMut::decode(r, s)),* + $($field: Decode::decode(r, s)),* } } } @@ -58,23 +58,18 @@ macro_rules! rpc_encode_decode { fn encode(self, w: &mut Writer, s: &mut S) { // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. - #[allow(non_upper_case_globals)] - mod tag { - #[repr(u8)] enum Tag { $($variant),* } - - $(pub(crate) const $variant: u8 = Tag::$variant as u8;)* - } + #[repr(u8)] enum Tag { $($variant),* } match self { $($name::$variant $(($field))* => { - tag::$variant.encode(w, s); + (Tag::$variant as u8).encode(w, s); $($field.encode(w, s);)* })* } } } - impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S> + impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> for $name $(<$($T),+>)? { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { @@ -89,7 +84,7 @@ macro_rules! rpc_encode_decode { match u8::decode(r, s) { $(tag::$variant => { - $(let $field = DecodeMut::decode(r, s);)* + $(let $field = Decode::decode(r, s);)* $name::$variant $(($field))* })* _ => unreachable!(), @@ -103,7 +98,7 @@ impl Encode for () { fn encode(self, _: &mut Writer, _: &mut S) {} } -impl DecodeMut<'_, '_, S> for () { +impl Decode<'_, '_, S> for () { fn decode(_: &mut Reader<'_>, _: &mut S) -> Self {} } @@ -113,7 +108,7 @@ impl Encode for u8 { } } -impl DecodeMut<'_, '_, S> for u8 { +impl Decode<'_, '_, S> for u8 { fn decode(r: &mut Reader<'_>, _: &mut S) -> Self { let x = r[0]; *r = &r[1..]; @@ -130,7 +125,7 @@ impl Encode for bool { } } -impl DecodeMut<'_, '_, S> for bool { +impl Decode<'_, '_, S> for bool { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { match u8::decode(r, s) { 0 => false, @@ -146,7 +141,7 @@ impl Encode for char { } } -impl DecodeMut<'_, '_, S> for char { +impl Decode<'_, '_, S> for char { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { char::from_u32(u32::decode(r, s)).unwrap() } @@ -158,7 +153,7 @@ impl Encode for NonZero { } } -impl DecodeMut<'_, '_, S> for NonZero { +impl Decode<'_, '_, S> for NonZero { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { Self::new(u32::decode(r, s)).unwrap() } @@ -171,11 +166,11 @@ impl, B: Encode> Encode for (A, B) { } } -impl<'a, S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> +impl<'a, S, A: for<'s> Decode<'a, 's, S>, B: for<'s> Decode<'a, 's, S>> Decode<'a, '_, S> for (A, B) { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { - (DecodeMut::decode(r, s), DecodeMut::decode(r, s)) + (Decode::decode(r, s), Decode::decode(r, s)) } } @@ -186,7 +181,7 @@ impl Encode for &[u8] { } } -impl<'a, S> DecodeMut<'a, '_, S> for &'a [u8] { +impl<'a, S> Decode<'a, '_, S> for &'a [u8] { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { let len = usize::decode(r, s); let xs = &r[..len]; @@ -201,7 +196,7 @@ impl Encode for &str { } } -impl<'a, S> DecodeMut<'a, '_, S> for &'a str { +impl<'a, S> Decode<'a, '_, S> for &'a str { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { str::from_utf8(<&[u8]>::decode(r, s)).unwrap() } @@ -213,7 +208,7 @@ impl Encode for String { } } -impl DecodeMut<'_, '_, S> for String { +impl Decode<'_, '_, S> for String { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { <&str>::decode(r, s).to_string() } @@ -228,7 +223,7 @@ impl> Encode for Vec { } } -impl<'a, S, T: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> for Vec { +impl<'a, S, T: for<'s> Decode<'a, 's, S>> Decode<'a, '_, S> for Vec { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { let len = usize::decode(r, s); let mut vec = Vec::with_capacity(len); @@ -288,7 +283,7 @@ impl Encode for PanicMessage { } } -impl DecodeMut<'_, '_, S> for PanicMessage { +impl Decode<'_, '_, S> for PanicMessage { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { match Option::::decode(r, s) { Some(s) => PanicMessage::String(s), diff --git a/library/proc_macro/src/bridge/selfless_reify.rs b/library/proc_macro/src/bridge/selfless_reify.rs index b06434a5ffee2..a53550e0b9e0c 100644 --- a/library/proc_macro/src/bridge/selfless_reify.rs +++ b/library/proc_macro/src/bridge/selfless_reify.rs @@ -50,7 +50,7 @@ macro_rules! define_reify_functions { >(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty { // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic // formatting becomes possible in `const fn`. - assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); + const { assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } $(extern $abi)? fn wrapper< $($($param,)*)? diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 2850e1099b700..051151b6c7c69 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -12,12 +12,12 @@ macro_rules! define_server_handles { ) => { #[allow(non_snake_case)] pub(super) struct HandleStore { - $($oty: handle::OwnedStore,)* - $($ity: handle::InternedStore,)* + $(pub(super) $oty: handle::OwnedStore,)* + $(pub(super) $ity: handle::InternedStore,)* } impl HandleStore { - fn new(handle_counters: &'static client::HandleCounters) -> Self { + pub(super) fn new(handle_counters: &'static client::HandleCounters) -> Self { HandleStore { $($oty: handle::OwnedStore::new(&handle_counters.$oty),)* $($ity: handle::InternedStore::new(&handle_counters.$ity),)* @@ -32,7 +32,7 @@ macro_rules! define_server_handles { } } - impl DecodeMut<'_, '_, HandleStore>> + impl Decode<'_, '_, HandleStore>> for Marked { fn decode(r: &mut Reader<'_>, s: &mut HandleStore>) -> Self { @@ -40,7 +40,7 @@ macro_rules! define_server_handles { } } - impl<'s, S: Types> DecodeMut<'_, 's, HandleStore>> + impl<'s, S: Types> Decode<'_, 's, HandleStore>> for &'s Marked { fn decode(r: &mut Reader<'_>, s: &'s mut HandleStore>) -> Self { @@ -48,7 +48,7 @@ macro_rules! define_server_handles { } } - impl<'s, S: Types> DecodeMut<'_, 's, HandleStore>> + impl<'s, S: Types> Decode<'_, 's, HandleStore>> for &'s mut Marked { fn decode( @@ -67,7 +67,7 @@ macro_rules! define_server_handles { } } - impl DecodeMut<'_, '_, HandleStore>> + impl Decode<'_, '_, HandleStore>> for Marked { fn decode(r: &mut Reader<'_>, s: &mut HandleStore>) -> Self { @@ -119,7 +119,7 @@ macro_rules! declare_server_traits { } with_api!(Self, self_, declare_server_traits); -pub(super) struct MarkedTypes(S); +pub(super) struct MarkedTypes(pub(super) S); impl Server for MarkedTypes { fn globals(&mut self) -> ExpnGlobals { @@ -150,9 +150,9 @@ macro_rules! define_mark_types_impls { } with_api!(Self, self_, define_mark_types_impls); -struct Dispatcher { - handle_store: HandleStore, - server: S, +pub(super) struct Dispatcher { + pub(super) handle_store: HandleStore>, + pub(super) server: MarkedTypes, } macro_rules! define_dispatcher_impl { @@ -167,7 +167,7 @@ macro_rules! define_dispatcher_impl { fn dispatch(&mut self, buf: Buffer) -> Buffer; } - impl DispatcherTrait for Dispatcher> { + impl DispatcherTrait for Dispatcher { $(type $name = as Types>::$name;)* fn dispatch(&mut self, mut buf: Buffer) -> Buffer { @@ -355,7 +355,7 @@ pub trait MessagePipe: Sized { fn run_server< S: Server, I: Encode>>, - O: for<'a, 's> DecodeMut<'a, 's, HandleStore>>, + O: for<'a, 's> Decode<'a, 's, HandleStore>>, >( strategy: &impl ExecutionStrategy, handle_counters: &'static client::HandleCounters, diff --git a/library/proc_macro/src/bridge/standalone.rs b/library/proc_macro/src/bridge/standalone.rs new file mode 100644 index 0000000000000..a7b9589e0fe12 --- /dev/null +++ b/library/proc_macro/src/bridge/standalone.rs @@ -0,0 +1,231 @@ +#![allow(unused_variables)] +use std::cell::RefCell; +use std::ops::{Bound, Range}; + +use crate::bridge::client::Symbol; +use crate::bridge::{Diagnostic, ExpnGlobals, Literal, TokenTree, server}; + +pub struct NoRustc; + +impl server::Span for NoRustc { + fn debug(&mut self, span: Self::Span) -> String { + format!("{} bytes({}..{})", span.hi - span.lo, span.lo, span.hi) + } + + fn parent(&mut self, span: Self::Span) -> Option { + todo!() + } + + fn source(&mut self, span: Self::Span) -> Self::Span { + todo!() + } + + fn byte_range(&mut self, span: Self::Span) -> Range { + todo!() + } + + fn start(&mut self, span: Self::Span) -> Self::Span { + Span { lo: span.lo, hi: span.lo } + } + + fn end(&mut self, span: Self::Span) -> Self::Span { + Span { lo: span.hi, hi: span.hi } + } + + fn line(&mut self, span: Self::Span) -> usize { + todo!() + } + + fn column(&mut self, span: Self::Span) -> usize { + todo!() + } + + fn file(&mut self, span: Self::Span) -> String { + todo!() + } + + fn local_file(&mut self, span: Self::Span) -> Option { + todo!() + } + + fn join(&mut self, span: Self::Span, other: Self::Span) -> Option { + todo!() + } + + fn subspan( + &mut self, + span: Self::Span, + start: Bound, + end: Bound, + ) -> Option { + let length = span.hi as usize - span.lo as usize; + + let start = match start { + Bound::Included(lo) => lo, + Bound::Excluded(lo) => lo.checked_add(1)?, + Bound::Unbounded => 0, + }; + + let end = match end { + Bound::Included(hi) => hi.checked_add(1)?, + Bound::Excluded(hi) => hi, + Bound::Unbounded => length, + }; + + // Bounds check the values, preventing addition overflow and OOB spans. + if start > u32::MAX as usize + || end > u32::MAX as usize + || (u32::MAX - start as u32) < span.lo + || (u32::MAX - end as u32) < span.lo + || start >= end + || end > length + { + return None; + } + + let new_lo = span.lo + start as u32; + let new_hi = span.lo + end as u32; + Some(Span { lo: new_lo, hi: new_hi }) + } + + fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span { + todo!() + } + + fn source_text(&mut self, span: Self::Span) -> Option { + todo!() + } + + fn save_span(&mut self, span: Self::Span) -> usize { + SAVED_SPANS.with_borrow_mut(|spans| { + let idx = spans.len(); + spans.push(span); + idx + }) + } + + fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span { + SAVED_SPANS.with_borrow(|spans| spans[id]) + } +} + +thread_local! { + static SAVED_SPANS: RefCell> = const { RefCell::new(Vec::new()) }; +} + +impl server::FreeFunctions for NoRustc { + fn injected_env_var(&mut self, var: &str) -> Option { + todo!() + } + + fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {} + + fn track_path(&mut self, _path: &str) {} + + fn literal_from_str(&mut self, s: &str) -> Result, ()> { + todo!() + } + + fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { + panic!("cannot emit diagnostic in standalone mode"); + } +} + +impl server::TokenStream for NoRustc { + fn is_empty(&mut self, tokens: &Self::TokenStream) -> bool { + tokens.0.is_empty() + } + + fn expand_expr(&mut self, tokens: &Self::TokenStream) -> Result { + todo!() + } + + fn from_str(&mut self, src: &str) -> Self::TokenStream { + todo!() + } + + fn to_string(&mut self, tokens: &Self::TokenStream) -> String { + todo!() + } + + fn from_token_tree( + &mut self, + tree: TokenTree, + ) -> Self::TokenStream { + TokenStream(vec![tree]) + } + + fn concat_trees( + &mut self, + base: Option, + trees: Vec>, + ) -> Self::TokenStream { + let mut base = base.unwrap_or_else(TokenStream::new); + base.0.extend(trees); + base + } + + fn concat_streams( + &mut self, + base: Option, + streams: Vec, + ) -> Self::TokenStream { + let mut base = base.unwrap_or_else(TokenStream::new); + for stream in streams { + base = self.concat_trees(Some(base), stream.0); + } + base + } + + fn into_trees( + &mut self, + tokens: Self::TokenStream, + ) -> Vec> { + tokens.0 + } +} + +pub struct FreeFunctions; +#[derive(Clone, Default)] +pub struct TokenStream(Vec>); +impl TokenStream { + pub fn new() -> Self { + Self(Vec::new()) + } +} + +#[derive(Hash, PartialEq, Eq, Clone, Copy)] +pub struct Span { + pub lo: u32, + pub hi: u32, +} +impl Span { + pub const DUMMY: Self = Self { lo: 0, hi: 0 }; +} + +impl server::Types for NoRustc { + type FreeFunctions = FreeFunctions; + type TokenStream = TokenStream; + type Span = Span; + type Symbol = Symbol; +} + +impl server::Server for NoRustc { + fn globals(&mut self) -> ExpnGlobals { + ExpnGlobals { def_site: Span::DUMMY, call_site: Span::DUMMY, mixed_site: Span::DUMMY } + } + + fn intern_symbol(ident: &str) -> Self::Symbol { + Symbol::new(ident) + } + + fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) { + symbol.with(f); + } +} + +impl server::Symbol for NoRustc { + fn normalize_and_validate_ident(&mut self, string: &str) -> Result { + todo!() + } +} diff --git a/library/proc_macro/src/bridge/symbol.rs b/library/proc_macro/src/bridge/symbol.rs index eb7d30f9a6cc9..0d6a725fddd98 100644 --- a/library/proc_macro/src/bridge/symbol.rs +++ b/library/proc_macro/src/bridge/symbol.rs @@ -102,7 +102,7 @@ impl Encode for Symbol { } } -impl DecodeMut<'_, '_, server::HandleStore>> +impl Decode<'_, '_, server::HandleStore>> for Marked { fn decode(r: &mut Reader<'_>, s: &mut server::HandleStore>) -> Self { @@ -118,7 +118,7 @@ impl Encode>> } } -impl DecodeMut<'_, '_, S> for Symbol { +impl Decode<'_, '_, S> for Symbol { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { Symbol::new(<&str>::decode(r, s)) } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 613abd7024e3f..673da6b371d6a 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -89,6 +89,28 @@ pub fn is_available() -> bool { bridge::client::is_available() } +/// Controls the extent to which the new standalone backend is used. +/// +/// When this will be stabilized, the default level will change from +/// `Never` to `FallbackOnly`. +#[unstable(feature = "proc_macro_standalone", issue = "130856")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum StandaloneLevel { + /// The standalone implementation is never used. This is the default. + Never, + /// The standalone implementation is only used outside of procedural macros. + FallbackOnly, + /// The standalone implementation is always used, even in procedural macros. + Always, +} + +/// Enables the new experimental standalone backend, which allows calling the +/// functions in this crate outside of procedural macros. +#[unstable(feature = "proc_macro_standalone", issue = "130856")] +pub fn enable_standalone(level: StandaloneLevel) { + bridge::client::enable_standalone(level); +} + /// The main type provided by this crate, representing an abstract stream of /// tokens, or, more specifically, a sequence of token trees. /// The type provides interfaces for iterating over those token trees and, conversely,