Skip to content

Commit 630b316

Browse files
Rollup merge of rust-lang#152166 - cyrgani:questionable-pm-cleanups, r=petrochenkov
cleanup some more things in `proc_macro::bridge` Each commit should be reviewable on its own.
2 parents 40a9cfb + 74d2616 commit 630b316

7 files changed

Lines changed: 126 additions & 157 deletions

File tree

library/proc_macro/src/bridge/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,15 @@ macro_rules! define_client_side {
121121
}
122122
}
123123
}
124-
with_api!(self, define_client_side);
124+
with_api!(define_client_side, TokenStream, Span, Symbol);
125125

126126
struct Bridge<'a> {
127127
/// Reusable buffer (only `clear`-ed, never shrunk), primarily
128128
/// used for making requests.
129129
cached_buffer: Buffer,
130130

131131
/// Server-side function that the client uses to make requests.
132-
dispatch: closure::Closure<'a, Buffer, Buffer>,
132+
dispatch: closure::Closure<'a>,
133133

134134
/// Provided globals for this macro expansion.
135135
globals: ExpnGlobals<Span>,
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
//! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`.
1+
//! Closure type (equivalent to `&mut dyn FnMut(Buffer) -> Buffer`) that's `repr(C)`.
22
33
use std::marker::PhantomData;
44

5+
use super::Buffer;
6+
57
#[repr(C)]
6-
pub(super) struct Closure<'a, A, R> {
7-
call: unsafe extern "C" fn(*mut Env, A) -> R,
8+
pub(super) struct Closure<'a> {
9+
call: extern "C" fn(*mut Env, Buffer) -> Buffer,
810
env: *mut Env,
911
// Prevent Send and Sync impls.
1012
//
@@ -14,17 +16,17 @@ pub(super) struct Closure<'a, A, R> {
1416

1517
struct Env;
1618

17-
impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> {
19+
impl<'a, F: FnMut(Buffer) -> Buffer> From<&'a mut F> for Closure<'a> {
1820
fn from(f: &'a mut F) -> Self {
19-
unsafe extern "C" fn call<A, R, F: FnMut(A) -> R>(env: *mut Env, arg: A) -> R {
21+
extern "C" fn call<F: FnMut(Buffer) -> Buffer>(env: *mut Env, arg: Buffer) -> Buffer {
2022
unsafe { (*(env as *mut _ as *mut F))(arg) }
2123
}
22-
Closure { call: call::<A, R, F>, env: f as *mut _ as *mut Env, _marker: PhantomData }
24+
Closure { call: call::<F>, env: f as *mut _ as *mut Env, _marker: PhantomData }
2325
}
2426
}
2527

26-
impl<'a, A, R> Closure<'a, A, R> {
27-
pub(super) fn call(&mut self, arg: A) -> R {
28-
unsafe { (self.call)(self.env, arg) }
28+
impl<'a> Closure<'a> {
29+
pub(super) fn call(&mut self, arg: Buffer) -> Buffer {
30+
(self.call)(self.env, arg)
2931
}
3032
}

library/proc_macro/src/bridge/mod.rs

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,71 +18,67 @@ use crate::{Delimiter, Level};
1818
/// Higher-order macro describing the server RPC API, allowing automatic
1919
/// generation of type-safe Rust APIs, both client-side and server-side.
2020
///
21-
/// `with_api!(MySelf, my_macro)` expands to:
21+
/// `with_api!(my_macro, MyTokenStream, MySpan, MySymbol)` expands to:
2222
/// ```rust,ignore (pseudo-code)
2323
/// my_macro! {
24-
/// fn lit_character(ch: char) -> MySelf::Literal;
25-
/// fn lit_span(lit: &MySelf::Literal) -> MySelf::Span;
26-
/// fn lit_set_span(lit: &mut MySelf::Literal, span: MySelf::Span);
24+
/// fn ts_clone(stream: &MyTokenStream) -> MyTokenStream;
25+
/// fn span_debug(span: &MySpan) -> String;
2726
/// // ...
2827
/// }
2928
/// ```
3029
///
31-
/// The first argument serves to customize the argument/return types,
32-
/// to enable several different usecases:
33-
///
34-
/// If `MySelf` is just `Self`, then the types are only valid inside
35-
/// a trait or a trait impl, where the trait has associated types
36-
/// for each of the API types. If non-associated types are desired,
37-
/// a module name (`self` in practice) can be used instead of `Self`.
30+
/// The second (`TokenStream`), third (`Span`) and fourth (`Symbol`)
31+
/// argument serve to customize the argument/return types that need
32+
/// special handling, to enable several different representations of
33+
/// these types.
3834
macro_rules! with_api {
39-
($S:ident, $m:ident) => {
35+
($m:ident, $TokenStream: path, $Span: path, $Symbol: path) => {
4036
$m! {
4137
fn injected_env_var(var: &str) -> Option<String>;
4238
fn track_env_var(var: &str, value: Option<&str>);
4339
fn track_path(path: &str);
44-
fn literal_from_str(s: &str) -> Result<Literal<$S::Span, $S::Symbol>, ()>;
45-
fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>);
46-
47-
fn ts_drop(stream: $S::TokenStream);
48-
fn ts_clone(stream: &$S::TokenStream) -> $S::TokenStream;
49-
fn ts_is_empty(stream: &$S::TokenStream) -> bool;
50-
fn ts_expand_expr(stream: &$S::TokenStream) -> Result<$S::TokenStream, ()>;
51-
fn ts_from_str(src: &str) -> $S::TokenStream;
52-
fn ts_to_string(stream: &$S::TokenStream) -> String;
40+
fn literal_from_str(s: &str) -> Result<Literal<$Span, $Symbol>, ()>;
41+
fn emit_diagnostic(diagnostic: Diagnostic<$Span>);
42+
43+
fn ts_drop(stream: $TokenStream);
44+
fn ts_clone(stream: &$TokenStream) -> $TokenStream;
45+
fn ts_is_empty(stream: &$TokenStream) -> bool;
46+
fn ts_expand_expr(stream: &$TokenStream) -> Result<$TokenStream, ()>;
47+
fn ts_from_str(src: &str) -> $TokenStream;
48+
fn ts_to_string(stream: &$TokenStream) -> String;
5349
fn ts_from_token_tree(
54-
tree: TokenTree<$S::TokenStream, $S::Span, $S::Symbol>,
55-
) -> $S::TokenStream;
50+
tree: TokenTree<$TokenStream, $Span, $Symbol>,
51+
) -> $TokenStream;
5652
fn ts_concat_trees(
57-
base: Option<$S::TokenStream>,
58-
trees: Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>,
59-
) -> $S::TokenStream;
53+
base: Option<$TokenStream>,
54+
trees: Vec<TokenTree<$TokenStream, $Span, $Symbol>>,
55+
) -> $TokenStream;
6056
fn ts_concat_streams(
61-
base: Option<$S::TokenStream>,
62-
streams: Vec<$S::TokenStream>,
63-
) -> $S::TokenStream;
57+
base: Option<$TokenStream>,
58+
streams: Vec<$TokenStream>,
59+
) -> $TokenStream;
6460
fn ts_into_trees(
65-
stream: $S::TokenStream
66-
) -> Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>;
67-
68-
fn span_debug(span: $S::Span) -> String;
69-
fn span_parent(span: $S::Span) -> Option<$S::Span>;
70-
fn span_source(span: $S::Span) -> $S::Span;
71-
fn span_byte_range(span: $S::Span) -> Range<usize>;
72-
fn span_start(span: $S::Span) -> $S::Span;
73-
fn span_end(span: $S::Span) -> $S::Span;
74-
fn span_line(span: $S::Span) -> usize;
75-
fn span_column(span: $S::Span) -> usize;
76-
fn span_file(span: $S::Span) -> String;
77-
fn span_local_file(span: $S::Span) -> Option<String>;
78-
fn span_join(span: $S::Span, other: $S::Span) -> Option<$S::Span>;
79-
fn span_subspan(span: $S::Span, start: Bound<usize>, end: Bound<usize>) -> Option<$S::Span>;
80-
fn span_resolved_at(span: $S::Span, at: $S::Span) -> $S::Span;
81-
fn span_source_text(span: $S::Span) -> Option<String>;
82-
fn span_save_span(span: $S::Span) -> usize;
83-
fn span_recover_proc_macro_span(id: usize) -> $S::Span;
84-
85-
fn symbol_normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>;
61+
stream: $TokenStream
62+
) -> Vec<TokenTree<$TokenStream, $Span, $Symbol>>;
63+
64+
fn span_debug(span: $Span) -> String;
65+
fn span_parent(span: $Span) -> Option<$Span>;
66+
fn span_source(span: $Span) -> $Span;
67+
fn span_byte_range(span: $Span) -> Range<usize>;
68+
fn span_start(span: $Span) -> $Span;
69+
fn span_end(span: $Span) -> $Span;
70+
fn span_line(span: $Span) -> usize;
71+
fn span_column(span: $Span) -> usize;
72+
fn span_file(span: $Span) -> String;
73+
fn span_local_file(span: $Span) -> Option<String>;
74+
fn span_join(span: $Span, other: $Span) -> Option<$Span>;
75+
fn span_subspan(span: $Span, start: Bound<usize>, end: Bound<usize>) -> Option<$Span>;
76+
fn span_resolved_at(span: $Span, at: $Span) -> $Span;
77+
fn span_source_text(span: $Span) -> Option<String>;
78+
fn span_save_span(span: $Span) -> usize;
79+
fn span_recover_proc_macro_span(id: usize) -> $Span;
80+
81+
fn symbol_normalize_and_validate_ident(string: &str) -> Result<$Symbol, ()>;
8682
}
8783
};
8884
}
@@ -126,7 +122,7 @@ pub struct BridgeConfig<'a> {
126122
input: Buffer,
127123

128124
/// Server-side function that the client uses to make requests.
129-
dispatch: closure::Closure<'a, Buffer, Buffer>,
125+
dispatch: closure::Closure<'a>,
130126

131127
/// If 'true', always invoke the default panic hook
132128
force_show_panics: bool,
@@ -146,7 +142,7 @@ macro_rules! declare_tags {
146142
rpc_encode_decode!(enum ApiTags { $($method),* });
147143
}
148144
}
149-
with_api!(self, declare_tags);
145+
with_api!(declare_tags, __, __, __);
150146

151147
/// Helper to wrap associated types to allow trait impl dispatch.
152148
/// That is, normally a pair of impls for `T::Foo` and `T::Bar`
@@ -173,7 +169,7 @@ impl<T, M> Mark for Marked<T, M> {
173169
self.value
174170
}
175171
}
176-
impl<'a, T, M> Mark for &'a Marked<T, M> {
172+
impl<'a, T> Mark for &'a Marked<T, client::TokenStream> {
177173
type Unmarked = &'a T;
178174
fn mark(_: Self::Unmarked) -> Self {
179175
unreachable!()
@@ -220,6 +216,8 @@ mark_noop! {
220216
Delimiter,
221217
LitKind,
222218
Level,
219+
Bound<usize>,
220+
Range<usize>,
223221
}
224222

225223
rpc_encode_decode!(
@@ -318,7 +316,7 @@ macro_rules! compound_traits {
318316
};
319317
}
320318

321-
compound_traits!(
319+
rpc_encode_decode!(
322320
enum Bound<T> {
323321
Included(x),
324322
Excluded(x),
@@ -390,7 +388,7 @@ pub struct Literal<Span, Symbol> {
390388
pub span: Span,
391389
}
392390

393-
compound_traits!(struct Literal<Sp, Sy> { kind, symbol, suffix, span });
391+
compound_traits!(struct Literal<Span, Symbol> { kind, symbol, suffix, span });
394392

395393
#[derive(Clone)]
396394
pub enum TokenTree<TokenStream, Span, Symbol> {
@@ -434,6 +432,6 @@ compound_traits!(
434432
struct ExpnGlobals<Span> { def_site, call_site, mixed_site }
435433
);
436434

437-
compound_traits!(
435+
rpc_encode_decode!(
438436
struct Range<T> { start, end }
439437
);

library/proc_macro/src/bridge/rpc.rs

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,45 +52,37 @@ macro_rules! rpc_encode_decode {
5252
}
5353
};
5454
(enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => {
55-
impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? {
56-
fn encode(self, w: &mut Buffer, s: &mut S) {
57-
// HACK(eddyb): `Tag` enum duplicated between the
58-
// two impls as there's no other place to stash it.
59-
#[allow(non_camel_case_types)]
60-
#[repr(u8)]
61-
enum Tag { $($variant),* }
62-
63-
match self {
64-
$($name::$variant $(($field))* => {
65-
(Tag::$variant as u8).encode(w, s);
66-
$($field.encode(w, s);)*
67-
})*
55+
#[allow(non_upper_case_globals, non_camel_case_types)]
56+
const _: () = {
57+
#[repr(u8)] enum Tag { $($variant),* }
58+
59+
$(const $variant: u8 = Tag::$variant as u8;)*
60+
61+
impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? {
62+
fn encode(self, w: &mut Buffer, s: &mut S) {
63+
match self {
64+
$($name::$variant $(($field))* => {
65+
$variant.encode(w, s);
66+
$($field.encode(w, s);)*
67+
})*
68+
}
6869
}
6970
}
70-
}
7171

72-
impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S>
73-
for $name $(<$($T),+>)?
74-
{
75-
fn decode(r: &mut &'a [u8], s: &mut S) -> Self {
76-
// HACK(eddyb): `Tag` enum duplicated between the
77-
// two impls as there's no other place to stash it.
78-
#[allow(non_upper_case_globals, non_camel_case_types)]
79-
mod tag {
80-
#[repr(u8)] enum Tag { $($variant),* }
81-
82-
$(pub(crate) const $variant: u8 = Tag::$variant as u8;)*
83-
}
84-
85-
match u8::decode(r, s) {
86-
$(tag::$variant => {
87-
$(let $field = Decode::decode(r, s);)*
88-
$name::$variant $(($field))*
89-
})*
90-
_ => unreachable!(),
72+
impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S>
73+
for $name $(<$($T),+>)?
74+
{
75+
fn decode(r: &mut &'a [u8], s: &mut S) -> Self {
76+
match u8::decode(r, s) {
77+
$($variant => {
78+
$(let $field = Decode::decode(r, s);)*
79+
$name::$variant $(($field))*
80+
})*
81+
_ => unreachable!(),
82+
}
9183
}
9284
}
93-
}
85+
};
9486
}
9587
}
9688

library/proc_macro/src/bridge/selfless_reify.rs

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -38,47 +38,27 @@
3838
3939
use std::mem;
4040

41-
// FIXME(eddyb) this could be `trait` impls except for the `const fn` requirement.
42-
macro_rules! define_reify_functions {
43-
($(
44-
fn $name:ident $(<$($param:ident),*>)?
45-
for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty;
46-
)+) => {
47-
$(pub(super) const fn $name<
48-
$($($param,)*)?
49-
F: Fn($($arg_ty),*) -> $ret_ty + Copy
50-
>(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty {
51-
// FIXME(eddyb) describe the `F` type (e.g. via `type_name::<F>`) once panic
52-
// formatting becomes possible in `const fn`.
53-
const { assert!(size_of::<F>() == 0, "selfless_reify: closure must be zero-sized"); }
54-
55-
$(extern $abi)? fn wrapper<
56-
$($($param,)*)?
57-
F: Fn($($arg_ty),*) -> $ret_ty + Copy
58-
>($($arg: $arg_ty),*) -> $ret_ty {
59-
let f = unsafe {
60-
// SAFETY: `F` satisfies all criteria for "out of thin air"
61-
// reconstructability (see module-level doc comment).
62-
mem::MaybeUninit::<F>::uninit().assume_init()
63-
};
64-
f($($arg),*)
65-
}
66-
let _f_proof = f;
67-
wrapper::<
68-
$($($param,)*)?
69-
F
70-
>
71-
})+
41+
pub(super) const fn reify_to_extern_c_fn_hrt_bridge<
42+
R,
43+
F: Fn(super::BridgeConfig<'_>) -> R + Copy,
44+
>(
45+
f: F,
46+
) -> extern "C" fn(super::BridgeConfig<'_>) -> R {
47+
// FIXME(eddyb) describe the `F` type (e.g. via `type_name::<F>`) once panic
48+
// formatting becomes possible in `const fn`.
49+
const {
50+
assert!(size_of::<F>() == 0, "selfless_reify: closure must be zero-sized");
7251
}
73-
}
74-
75-
define_reify_functions! {
76-
fn _reify_to_extern_c_fn_unary<A, R> for extern "C" fn(arg: A) -> R;
77-
78-
// HACK(eddyb) this abstraction is used with `for<'a> fn(BridgeConfig<'a>)
79-
// -> T` but that doesn't work with just `reify_to_extern_c_fn_unary`
80-
// because of the `fn` pointer type being "higher-ranked" (i.e. the
81-
// `for<'a>` binder).
82-
// FIXME(eddyb) try to remove the lifetime from `BridgeConfig`, that'd help.
83-
fn reify_to_extern_c_fn_hrt_bridge<R> for extern "C" fn(bridge: super::BridgeConfig<'_>) -> R;
52+
extern "C" fn wrapper<R, F: Fn(super::BridgeConfig<'_>) -> R + Copy>(
53+
bridge: super::BridgeConfig<'_>,
54+
) -> R {
55+
let f = unsafe {
56+
// SAFETY: `F` satisfies all criteria for "out of thin air"
57+
// reconstructability (see module-level doc comment).
58+
mem::conjure_zst::<F>()
59+
};
60+
f(bridge)
61+
}
62+
let _f_proof = f;
63+
wrapper::<R, F>
8464
}

0 commit comments

Comments
 (0)