Skip to content

Commit dfac64b

Browse files
authored
Rollup merge of rust-lang#65900 - eddyb:proc-macro-cleanup, r=alexcrichton
proc_macro: clean up bridge::client::__run_expand{1,2} a bit. See commit titles/diffs for more details. The first commit is made possible by rust-lang#53451 being fixed (almost a year ago). The last commit should remove the need for `#[allow(improper_ctypes)]` in rust-lang#65134.
2 parents 4bb91c7 + b586344 commit dfac64b

File tree

1 file changed

+28
-54
lines changed

1 file changed

+28
-54
lines changed

src/libproc_macro/bridge/client.rs

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ macro_rules! define_handles {
1515
}
1616

1717
impl HandleCounters {
18-
// FIXME(#53451) public to work around `Cannot create local mono-item` ICE.
19-
pub extern "C" fn get() -> &'static Self {
18+
// FIXME(eddyb) use a reference to the `static COUNTERS`, intead of
19+
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
20+
extern "C" fn get() -> &'static Self {
2021
static COUNTERS: HandleCounters = HandleCounters {
2122
$($oty: AtomicUsize::new(1),)*
2223
$($ity: AtomicUsize::new(1),)*
@@ -333,29 +334,32 @@ impl Bridge<'_> {
333334
#[repr(C)]
334335
#[derive(Copy, Clone)]
335336
pub struct Client<F> {
337+
// FIXME(eddyb) use a reference to the `static COUNTERS`, intead of
338+
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
336339
pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
337340
pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>,
338341
pub(super) f: F,
339342
}
340343

341-
// FIXME(#53451) public to work around `Cannot create local mono-item` ICE,
342-
// affecting not only the function itself, but also the `BridgeState` `thread_local!`.
343-
pub extern "C" fn __run_expand1(
344+
/// Client-side helper for handling client panics, entering the bridge,
345+
/// deserializing input and serializing output.
346+
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
347+
fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
344348
mut bridge: Bridge<'_>,
345-
f: fn(crate::TokenStream) -> crate::TokenStream,
349+
f: impl FnOnce(A) -> R,
346350
) -> Buffer<u8> {
347351
// The initial `cached_buffer` contains the input.
348352
let mut b = bridge.cached_buffer.take();
349353

350354
panic::catch_unwind(panic::AssertUnwindSafe(|| {
351355
bridge.enter(|| {
352356
let reader = &mut &b[..];
353-
let input = TokenStream::decode(reader, &mut ());
357+
let input = A::decode(reader, &mut ());
354358

355359
// Put the `cached_buffer` back in the `Bridge`, for requests.
356360
Bridge::with(|bridge| bridge.cached_buffer = b.take());
357361

358-
let output = f(crate::TokenStream(input)).0;
362+
let output = f(input);
359363

360364
// Take the `cached_buffer` back out, for the output value.
361365
b = Bridge::with(|bridge| bridge.cached_buffer.take());
@@ -383,65 +387,35 @@ pub extern "C" fn __run_expand1(
383387

384388
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
385389
pub const fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
390+
extern "C" fn run(
391+
bridge: Bridge<'_>,
392+
f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
393+
) -> Buffer<u8> {
394+
run_client(bridge, |input| f(crate::TokenStream(input)).0)
395+
}
386396
Client {
387397
get_handle_counters: HandleCounters::get,
388-
run: __run_expand1,
398+
run,
389399
f,
390400
}
391401
}
392402
}
393403

394-
// FIXME(#53451) public to work around `Cannot create local mono-item` ICE,
395-
// affecting not only the function itself, but also the `BridgeState` `thread_local!`.
396-
pub extern "C" fn __run_expand2(
397-
mut bridge: Bridge<'_>,
398-
f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
399-
) -> Buffer<u8> {
400-
// The initial `cached_buffer` contains the input.
401-
let mut b = bridge.cached_buffer.take();
402-
403-
panic::catch_unwind(panic::AssertUnwindSafe(|| {
404-
bridge.enter(|| {
405-
let reader = &mut &b[..];
406-
let input = TokenStream::decode(reader, &mut ());
407-
let input2 = TokenStream::decode(reader, &mut ());
408-
409-
// Put the `cached_buffer` back in the `Bridge`, for requests.
410-
Bridge::with(|bridge| bridge.cached_buffer = b.take());
411-
412-
let output = f(crate::TokenStream(input), crate::TokenStream(input2)).0;
413-
414-
// Take the `cached_buffer` back out, for the output value.
415-
b = Bridge::with(|bridge| bridge.cached_buffer.take());
416-
417-
// HACK(eddyb) Separate encoding a success value (`Ok(output)`)
418-
// from encoding a panic (`Err(e: PanicMessage)`) to avoid
419-
// having handles outside the `bridge.enter(|| ...)` scope, and
420-
// to catch panics that could happen while encoding the success.
421-
//
422-
// Note that panics should be impossible beyond this point, but
423-
// this is defensively trying to avoid any accidental panicking
424-
// reaching the `extern "C"` (which should `abort` but may not
425-
// at the moment, so this is also potentially preventing UB).
426-
b.clear();
427-
Ok::<_, ()>(output).encode(&mut b, &mut ());
428-
})
429-
}))
430-
.map_err(PanicMessage::from)
431-
.unwrap_or_else(|e| {
432-
b.clear();
433-
Err::<(), _>(e).encode(&mut b, &mut ());
434-
});
435-
b
436-
}
437-
438404
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
439405
pub const fn expand2(
440406
f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream
441407
) -> Self {
408+
extern "C" fn run(
409+
bridge: Bridge<'_>,
410+
f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
411+
) -> Buffer<u8> {
412+
run_client(bridge, |(input, input2)| {
413+
f(crate::TokenStream(input), crate::TokenStream(input2)).0
414+
})
415+
}
442416
Client {
443417
get_handle_counters: HandleCounters::get,
444-
run: __run_expand2,
418+
run,
445419
f,
446420
}
447421
}

0 commit comments

Comments
 (0)