mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
proc_macro: cache static spans in client's thread-local state
This greatly improves the performance of the very frequently called `call_site()` macro when running in a cross-thread configuration.
This commit is contained in:
parent
1aabd8a4a6
commit
55f052d9c9
@ -370,7 +370,10 @@ impl<'a, 'b> Rustc<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
|
fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
|
||||||
Literal { lit: token::Lit::new(kind, symbol, suffix), span: server::Span::call_site(self) }
|
Literal {
|
||||||
|
lit: token::Lit::new(kind, symbol, suffix),
|
||||||
|
span: server::Context::call_site(self),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +550,7 @@ impl server::Group for Rustc<'_, '_> {
|
|||||||
Group {
|
Group {
|
||||||
delimiter,
|
delimiter,
|
||||||
stream: stream.unwrap_or_default(),
|
stream: stream.unwrap_or_default(),
|
||||||
span: DelimSpan::from_single(server::Span::call_site(self)),
|
span: DelimSpan::from_single(server::Context::call_site(self)),
|
||||||
flatten: false,
|
flatten: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -579,7 +582,7 @@ impl server::Group for Rustc<'_, '_> {
|
|||||||
|
|
||||||
impl server::Punct for Rustc<'_, '_> {
|
impl server::Punct for Rustc<'_, '_> {
|
||||||
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
|
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
|
||||||
Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
|
Punct::new(ch, spacing == Spacing::Joint, server::Context::call_site(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_char(&mut self, punct: Self::Punct) -> char {
|
fn as_char(&mut self, punct: Self::Punct) -> char {
|
||||||
@ -829,18 +832,6 @@ impl server::Span for Rustc<'_, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_site(&mut self) -> Self::Span {
|
|
||||||
self.def_site
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_site(&mut self) -> Self::Span {
|
|
||||||
self.call_site
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mixed_site(&mut self) -> Self::Span {
|
|
||||||
self.mixed_site
|
|
||||||
}
|
|
||||||
|
|
||||||
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
|
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
|
||||||
self.sess().source_map().lookup_char_pos(span.lo()).file
|
self.sess().source_map().lookup_char_pos(span.lo()).file
|
||||||
}
|
}
|
||||||
@ -926,3 +917,17 @@ impl server::Span for Rustc<'_, '_> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl server::Context for Rustc<'_, '_> {
|
||||||
|
fn def_site(&mut self) -> Self::Span {
|
||||||
|
self.def_site
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_site(&mut self) -> Self::Span {
|
||||||
|
self.call_site
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mixed_site(&mut self) -> Self::Span {
|
||||||
|
self.mixed_site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -230,6 +230,20 @@ impl Clone for SourceFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Span {
|
||||||
|
pub(crate) fn def_site() -> Span {
|
||||||
|
Bridge::with(|bridge| bridge.context.def_site)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn call_site() -> Span {
|
||||||
|
Bridge::with(|bridge| bridge.context.call_site)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mixed_site() -> Span {
|
||||||
|
Bridge::with(|bridge| bridge.context.mixed_site)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Span {
|
impl fmt::Debug for Span {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str(&self.debug())
|
f.write_str(&self.debug())
|
||||||
@ -263,6 +277,21 @@ macro_rules! define_client_side {
|
|||||||
}
|
}
|
||||||
with_api!(self, self, define_client_side);
|
with_api!(self, self, define_client_side);
|
||||||
|
|
||||||
|
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>,
|
||||||
|
|
||||||
|
/// Provided context for this macro expansion.
|
||||||
|
context: ExpnContext<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> !Send for Bridge<'a> {}
|
||||||
|
impl<'a> !Sync for Bridge<'a> {}
|
||||||
|
|
||||||
enum BridgeState<'a> {
|
enum BridgeState<'a> {
|
||||||
/// No server is currently connected to this client.
|
/// No server is currently connected to this client.
|
||||||
NotConnected,
|
NotConnected,
|
||||||
@ -305,34 +334,6 @@ impl BridgeState<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Bridge<'_> {
|
impl Bridge<'_> {
|
||||||
pub(crate) fn is_available() -> bool {
|
|
||||||
BridgeState::with(|state| match state {
|
|
||||||
BridgeState::Connected(_) | BridgeState::InUse => true,
|
|
||||||
BridgeState::NotConnected => false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enter<R>(self, f: impl FnOnce() -> R) -> R {
|
|
||||||
let force_show_panics = self.force_show_panics;
|
|
||||||
// Hide the default panic output within `proc_macro` expansions.
|
|
||||||
// NB. the server can't do this because it may use a different libstd.
|
|
||||||
static HIDE_PANICS_DURING_EXPANSION: Once = Once::new();
|
|
||||||
HIDE_PANICS_DURING_EXPANSION.call_once(|| {
|
|
||||||
let prev = panic::take_hook();
|
|
||||||
panic::set_hook(Box::new(move |info| {
|
|
||||||
let show = BridgeState::with(|state| match state {
|
|
||||||
BridgeState::NotConnected => true,
|
|
||||||
BridgeState::Connected(_) | BridgeState::InUse => force_show_panics,
|
|
||||||
});
|
|
||||||
if show {
|
|
||||||
prev(info)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
BRIDGE_STATE.with(|state| state.set(BridgeState::Connected(self), f))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
|
fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
|
||||||
BridgeState::with(|state| match state {
|
BridgeState::with(|state| match state {
|
||||||
BridgeState::NotConnected => {
|
BridgeState::NotConnected => {
|
||||||
@ -346,6 +347,13 @@ impl Bridge<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_available() -> bool {
|
||||||
|
BridgeState::with(|state| match state {
|
||||||
|
BridgeState::Connected(_) | BridgeState::InUse => true,
|
||||||
|
BridgeState::NotConnected => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// A client-side RPC entry-point, which may be using a different `proc_macro`
|
/// 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.
|
/// from the one used by the server, but can be invoked compatibly.
|
||||||
///
|
///
|
||||||
@ -363,7 +371,7 @@ pub struct Client<I, O> {
|
|||||||
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
|
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
|
||||||
pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
|
pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
|
||||||
|
|
||||||
pub(super) run: extern "C" fn(Bridge<'_>) -> Buffer,
|
pub(super) run: extern "C" fn(BridgeConfig<'_>) -> Buffer,
|
||||||
|
|
||||||
pub(super) _marker: PhantomData<fn(I) -> O>,
|
pub(super) _marker: PhantomData<fn(I) -> O>,
|
||||||
}
|
}
|
||||||
@ -375,40 +383,62 @@ impl<I, O> Clone for Client<I, O> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maybe_install_panic_hook(force_show_panics: bool) {
|
||||||
|
// Hide the default panic output within `proc_macro` expansions.
|
||||||
|
// NB. the server can't do this because it may use a different libstd.
|
||||||
|
static HIDE_PANICS_DURING_EXPANSION: Once = Once::new();
|
||||||
|
HIDE_PANICS_DURING_EXPANSION.call_once(|| {
|
||||||
|
let prev = panic::take_hook();
|
||||||
|
panic::set_hook(Box::new(move |info| {
|
||||||
|
let show = BridgeState::with(|state| match state {
|
||||||
|
BridgeState::NotConnected => true,
|
||||||
|
BridgeState::Connected(_) | BridgeState::InUse => force_show_panics,
|
||||||
|
});
|
||||||
|
if show {
|
||||||
|
prev(info)
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Client-side helper for handling client panics, entering the bridge,
|
/// Client-side helper for handling client panics, entering the bridge,
|
||||||
/// deserializing input and serializing output.
|
/// deserializing input and serializing output.
|
||||||
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
|
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
|
||||||
fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
||||||
mut bridge: Bridge<'_>,
|
config: BridgeConfig<'_>,
|
||||||
f: impl FnOnce(A) -> R,
|
f: impl FnOnce(A) -> R,
|
||||||
) -> Buffer {
|
) -> Buffer {
|
||||||
// The initial `cached_buffer` contains the input.
|
let BridgeConfig { input: mut buf, dispatch, force_show_panics, .. } = config;
|
||||||
let mut buf = bridge.cached_buffer.take();
|
|
||||||
|
|
||||||
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||||
bridge.enter(|| {
|
maybe_install_panic_hook(force_show_panics);
|
||||||
let reader = &mut &buf[..];
|
|
||||||
let input = A::decode(reader, &mut ());
|
|
||||||
|
|
||||||
// Put the `cached_buffer` back in the `Bridge`, for requests.
|
let reader = &mut &buf[..];
|
||||||
Bridge::with(|bridge| bridge.cached_buffer = buf.take());
|
let (input, context) = <(A, ExpnContext<Span>)>::decode(reader, &mut ());
|
||||||
|
|
||||||
let output = f(input);
|
// Put the buffer we used for input back in the `Bridge` for requests.
|
||||||
|
let new_state =
|
||||||
|
BridgeState::Connected(Bridge { cached_buffer: buf.take(), dispatch, context });
|
||||||
|
|
||||||
// Take the `cached_buffer` back out, for the output value.
|
BRIDGE_STATE.with(|state| {
|
||||||
buf = Bridge::with(|bridge| bridge.cached_buffer.take());
|
state.set(new_state, || {
|
||||||
|
let output = f(input);
|
||||||
|
|
||||||
// HACK(eddyb) Separate encoding a success value (`Ok(output)`)
|
// Take the `cached_buffer` back out, for the output value.
|
||||||
// from encoding a panic (`Err(e: PanicMessage)`) to avoid
|
buf = Bridge::with(|bridge| bridge.cached_buffer.take());
|
||||||
// having handles outside the `bridge.enter(|| ...)` scope, and
|
|
||||||
// to catch panics that could happen while encoding the success.
|
// HACK(eddyb) Separate encoding a success value (`Ok(output)`)
|
||||||
//
|
// from encoding a panic (`Err(e: PanicMessage)`) to avoid
|
||||||
// Note that panics should be impossible beyond this point, but
|
// having handles outside the `bridge.enter(|| ...)` scope, and
|
||||||
// this is defensively trying to avoid any accidental panicking
|
// to catch panics that could happen while encoding the success.
|
||||||
// reaching the `extern "C"` (which should `abort` but might not
|
//
|
||||||
// at the moment, so this is also potentially preventing UB).
|
// Note that panics should be impossible beyond this point, but
|
||||||
buf.clear();
|
// this is defensively trying to avoid any accidental panicking
|
||||||
Ok::<_, ()>(output).encode(&mut buf, &mut ());
|
// reaching the `extern "C"` (which should `abort` but might not
|
||||||
|
// at the moment, so this is also potentially preventing UB).
|
||||||
|
buf.clear();
|
||||||
|
Ok::<_, ()>(output).encode(&mut buf, &mut ());
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
.map_err(PanicMessage::from)
|
.map_err(PanicMessage::from)
|
||||||
|
@ -151,9 +151,6 @@ macro_rules! with_api {
|
|||||||
},
|
},
|
||||||
Span {
|
Span {
|
||||||
fn debug($self: $S::Span) -> String;
|
fn debug($self: $S::Span) -> String;
|
||||||
fn def_site() -> $S::Span;
|
|
||||||
fn call_site() -> $S::Span;
|
|
||||||
fn mixed_site() -> $S::Span;
|
|
||||||
fn source_file($self: $S::Span) -> $S::SourceFile;
|
fn source_file($self: $S::Span) -> $S::SourceFile;
|
||||||
fn parent($self: $S::Span) -> Option<$S::Span>;
|
fn parent($self: $S::Span) -> Option<$S::Span>;
|
||||||
fn source($self: $S::Span) -> $S::Span;
|
fn source($self: $S::Span) -> $S::Span;
|
||||||
@ -213,16 +210,15 @@ use buffer::Buffer;
|
|||||||
pub use rpc::PanicMessage;
|
pub use rpc::PanicMessage;
|
||||||
use rpc::{Decode, DecodeMut, Encode, Reader, Writer};
|
use rpc::{Decode, DecodeMut, Encode, Reader, Writer};
|
||||||
|
|
||||||
/// An active connection between a server and a client.
|
/// Configuration for establishing an active connection between a server and a
|
||||||
/// The server creates the bridge (`Bridge::run_server` in `server.rs`),
|
/// client. The server creates the bridge config (`run_server` in `server.rs`),
|
||||||
/// then passes it to the client through the function pointer in the `run`
|
/// then passes it to the client through the function pointer in the `run` field
|
||||||
/// field of `client::Client`. The client holds its copy of the `Bridge`
|
/// of `client::Client`. The client constructs a local `Bridge` from the config
|
||||||
/// in TLS during its execution (`Bridge::{enter, with}` in `client.rs`).
|
/// in TLS during its execution (`Bridge::{enter, with}` in `client.rs`).
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Bridge<'a> {
|
pub struct BridgeConfig<'a> {
|
||||||
/// Reusable buffer (only `clear`-ed, never shrunk), primarily
|
/// Buffer used to pass initial input to the client.
|
||||||
/// used for making requests, but also for passing input to client.
|
input: Buffer,
|
||||||
cached_buffer: Buffer,
|
|
||||||
|
|
||||||
/// Server-side function that the client uses to make requests.
|
/// Server-side function that the client uses to make requests.
|
||||||
dispatch: closure::Closure<'a, Buffer, Buffer>,
|
dispatch: closure::Closure<'a, Buffer, Buffer>,
|
||||||
@ -379,6 +375,25 @@ rpc_encode_decode!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! mark_compound {
|
macro_rules! mark_compound {
|
||||||
|
(struct $name:ident <$($T:ident),+> { $($field:ident),* $(,)? }) => {
|
||||||
|
impl<$($T: Mark),+> Mark for $name <$($T),+> {
|
||||||
|
type Unmarked = $name <$($T::Unmarked),+>;
|
||||||
|
fn mark(unmarked: Self::Unmarked) -> Self {
|
||||||
|
$name {
|
||||||
|
$($field: Mark::mark(unmarked.$field)),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<$($T: Unmark),+> Unmark for $name <$($T),+> {
|
||||||
|
type Unmarked = $name <$($T::Unmarked),+>;
|
||||||
|
fn unmark(self) -> Self::Unmarked {
|
||||||
|
$name {
|
||||||
|
$($field: Unmark::unmark(self.$field)),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
(enum $name:ident <$($T:ident),+> { $($variant:ident $(($field:ident))?),* $(,)? }) => {
|
(enum $name:ident <$($T:ident),+> { $($variant:ident $(($field:ident))?),* $(,)? }) => {
|
||||||
impl<$($T: Mark),+> Mark for $name <$($T),+> {
|
impl<$($T: Mark),+> Mark for $name <$($T),+> {
|
||||||
type Unmarked = $name <$($T::Unmarked),+>;
|
type Unmarked = $name <$($T::Unmarked),+>;
|
||||||
@ -449,3 +464,16 @@ compound_traits!(
|
|||||||
Literal(tt),
|
Literal(tt),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Context provided alongside the initial inputs for a macro expansion.
|
||||||
|
/// Provides values such as spans which are used frequently to avoid RPC.
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ExpnContext<S> {
|
||||||
|
def_site: S,
|
||||||
|
call_site: S,
|
||||||
|
mixed_site: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
compound_traits!(
|
||||||
|
struct ExpnContext<Sp> { def_site, call_site, mixed_site }
|
||||||
|
);
|
||||||
|
@ -75,9 +75,10 @@ macro_rules! define_reify_functions {
|
|||||||
define_reify_functions! {
|
define_reify_functions! {
|
||||||
fn _reify_to_extern_c_fn_unary<A, R> for extern "C" fn(arg: A) -> R;
|
fn _reify_to_extern_c_fn_unary<A, R> for extern "C" fn(arg: A) -> R;
|
||||||
|
|
||||||
// HACK(eddyb) this abstraction is used with `for<'a> fn(Bridge<'a>) -> T`
|
// HACK(eddyb) this abstraction is used with `for<'a> fn(BridgeConfig<'a>)
|
||||||
// but that doesn't work with just `reify_to_extern_c_fn_unary` because of
|
// -> T` but that doesn't work with just `reify_to_extern_c_fn_unary`
|
||||||
// the `fn` pointer type being "higher-ranked" (i.e. the `for<'a>` binder).
|
// because of the `fn` pointer type being "higher-ranked" (i.e. the
|
||||||
// FIXME(eddyb) try to remove the lifetime from `Bridge`, that'd help.
|
// `for<'a>` binder).
|
||||||
fn reify_to_extern_c_fn_hrt_bridge<R> for extern "C" fn(bridge: super::Bridge<'_>) -> R;
|
// FIXME(eddyb) try to remove the lifetime from `BridgeConfig`, that'd help.
|
||||||
|
fn reify_to_extern_c_fn_hrt_bridge<R> for extern "C" fn(bridge: super::BridgeConfig<'_>) -> R;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,13 @@ macro_rules! associated_fn {
|
|||||||
($($item:tt)*) => ($($item)*;)
|
($($item:tt)*) => ($($item)*;)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper methods defined by `Server` types not invoked over RPC.
|
||||||
|
pub trait Context: Types {
|
||||||
|
fn def_site(&mut self) -> Self::Span;
|
||||||
|
fn call_site(&mut self) -> Self::Span;
|
||||||
|
fn mixed_site(&mut self) -> Self::Span;
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! declare_server_traits {
|
macro_rules! declare_server_traits {
|
||||||
($($name:ident {
|
($($name:ident {
|
||||||
$(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
|
$(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
|
||||||
@ -38,14 +45,26 @@ macro_rules! declare_server_traits {
|
|||||||
$(associated_fn!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)*
|
$(associated_fn!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)*
|
||||||
})*
|
})*
|
||||||
|
|
||||||
pub trait Server: Types $(+ $name)* {}
|
pub trait Server: Types + Context $(+ $name)* {}
|
||||||
impl<S: Types $(+ $name)*> Server for S {}
|
impl<S: Types + Context $(+ $name)*> Server for S {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
with_api!(Self, self_, declare_server_traits);
|
with_api!(Self, self_, declare_server_traits);
|
||||||
|
|
||||||
pub(super) struct MarkedTypes<S: Types>(S);
|
pub(super) struct MarkedTypes<S: Types>(S);
|
||||||
|
|
||||||
|
impl<S: Context> Context for MarkedTypes<S> {
|
||||||
|
fn def_site(&mut self) -> Self::Span {
|
||||||
|
<_>::mark(Context::def_site(&mut self.0))
|
||||||
|
}
|
||||||
|
fn call_site(&mut self) -> Self::Span {
|
||||||
|
<_>::mark(Context::call_site(&mut self.0))
|
||||||
|
}
|
||||||
|
fn mixed_site(&mut self) -> Self::Span {
|
||||||
|
<_>::mark(Context::mixed_site(&mut self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! define_mark_types_impls {
|
macro_rules! define_mark_types_impls {
|
||||||
($($name:ident {
|
($($name:ident {
|
||||||
$(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
|
$(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
|
||||||
@ -120,7 +139,7 @@ pub trait ExecutionStrategy {
|
|||||||
&self,
|
&self,
|
||||||
dispatcher: &mut impl DispatcherTrait,
|
dispatcher: &mut impl DispatcherTrait,
|
||||||
input: Buffer,
|
input: Buffer,
|
||||||
run_client: extern "C" fn(Bridge<'_>) -> Buffer,
|
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
|
||||||
force_show_panics: bool,
|
force_show_panics: bool,
|
||||||
) -> Buffer;
|
) -> Buffer;
|
||||||
}
|
}
|
||||||
@ -132,13 +151,13 @@ impl ExecutionStrategy for SameThread {
|
|||||||
&self,
|
&self,
|
||||||
dispatcher: &mut impl DispatcherTrait,
|
dispatcher: &mut impl DispatcherTrait,
|
||||||
input: Buffer,
|
input: Buffer,
|
||||||
run_client: extern "C" fn(Bridge<'_>) -> Buffer,
|
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
|
||||||
force_show_panics: bool,
|
force_show_panics: bool,
|
||||||
) -> Buffer {
|
) -> Buffer {
|
||||||
let mut dispatch = |buf| dispatcher.dispatch(buf);
|
let mut dispatch = |buf| dispatcher.dispatch(buf);
|
||||||
|
|
||||||
run_client(Bridge {
|
run_client(BridgeConfig {
|
||||||
cached_buffer: input,
|
input,
|
||||||
dispatch: (&mut dispatch).into(),
|
dispatch: (&mut dispatch).into(),
|
||||||
force_show_panics,
|
force_show_panics,
|
||||||
_marker: marker::PhantomData,
|
_marker: marker::PhantomData,
|
||||||
@ -156,7 +175,7 @@ impl ExecutionStrategy for CrossThread1 {
|
|||||||
&self,
|
&self,
|
||||||
dispatcher: &mut impl DispatcherTrait,
|
dispatcher: &mut impl DispatcherTrait,
|
||||||
input: Buffer,
|
input: Buffer,
|
||||||
run_client: extern "C" fn(Bridge<'_>) -> Buffer,
|
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
|
||||||
force_show_panics: bool,
|
force_show_panics: bool,
|
||||||
) -> Buffer {
|
) -> Buffer {
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
@ -170,8 +189,8 @@ impl ExecutionStrategy for CrossThread1 {
|
|||||||
res_rx.recv().unwrap()
|
res_rx.recv().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
run_client(Bridge {
|
run_client(BridgeConfig {
|
||||||
cached_buffer: input,
|
input,
|
||||||
dispatch: (&mut dispatch).into(),
|
dispatch: (&mut dispatch).into(),
|
||||||
force_show_panics,
|
force_show_panics,
|
||||||
_marker: marker::PhantomData,
|
_marker: marker::PhantomData,
|
||||||
@ -193,7 +212,7 @@ impl ExecutionStrategy for CrossThread2 {
|
|||||||
&self,
|
&self,
|
||||||
dispatcher: &mut impl DispatcherTrait,
|
dispatcher: &mut impl DispatcherTrait,
|
||||||
input: Buffer,
|
input: Buffer,
|
||||||
run_client: extern "C" fn(Bridge<'_>) -> Buffer,
|
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
|
||||||
force_show_panics: bool,
|
force_show_panics: bool,
|
||||||
) -> Buffer {
|
) -> Buffer {
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@ -219,8 +238,8 @@ impl ExecutionStrategy for CrossThread2 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let r = run_client(Bridge {
|
let r = run_client(BridgeConfig {
|
||||||
cached_buffer: input,
|
input,
|
||||||
dispatch: (&mut dispatch).into(),
|
dispatch: (&mut dispatch).into(),
|
||||||
force_show_panics,
|
force_show_panics,
|
||||||
_marker: marker::PhantomData,
|
_marker: marker::PhantomData,
|
||||||
@ -258,14 +277,20 @@ fn run_server<
|
|||||||
handle_counters: &'static client::HandleCounters,
|
handle_counters: &'static client::HandleCounters,
|
||||||
server: S,
|
server: S,
|
||||||
input: I,
|
input: I,
|
||||||
run_client: extern "C" fn(Bridge<'_>) -> Buffer,
|
run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
|
||||||
force_show_panics: bool,
|
force_show_panics: bool,
|
||||||
) -> Result<O, PanicMessage> {
|
) -> Result<O, PanicMessage> {
|
||||||
let mut dispatcher =
|
let mut dispatcher =
|
||||||
Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) };
|
Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) };
|
||||||
|
|
||||||
|
let expn_context = ExpnContext {
|
||||||
|
def_site: dispatcher.server.def_site(),
|
||||||
|
call_site: dispatcher.server.call_site(),
|
||||||
|
mixed_site: dispatcher.server.mixed_site(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new();
|
||||||
input.encode(&mut buf, &mut dispatcher.handle_store);
|
(input, expn_context).encode(&mut buf, &mut dispatcher.handle_store);
|
||||||
|
|
||||||
buf = strategy.run_bridge_and_client(&mut dispatcher, buf, run_client, force_show_panics);
|
buf = strategy.run_bridge_and_client(&mut dispatcher, buf, run_client, force_show_panics);
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ use std::{error, fmt, iter};
|
|||||||
/// inside of a procedural macro, false if invoked from any other binary.
|
/// inside of a procedural macro, false if invoked from any other binary.
|
||||||
#[stable(feature = "proc_macro_is_available", since = "1.57.0")]
|
#[stable(feature = "proc_macro_is_available", since = "1.57.0")]
|
||||||
pub fn is_available() -> bool {
|
pub fn is_available() -> bool {
|
||||||
bridge::Bridge::is_available()
|
bridge::client::is_available()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main type provided by this crate, representing an abstract stream of
|
/// The main type provided by this crate, representing an abstract stream of
|
||||||
|
Loading…
Reference in New Issue
Block a user