@@ -241,6 +241,20 @@ impl Clone for SourceFile {
241
241
}
242
242
}
243
243
244
+ impl Span {
245
+ pub ( crate ) fn def_site ( ) -> Span {
246
+ Bridge :: with ( |bridge| bridge. context . def_site )
247
+ }
248
+
249
+ pub ( crate ) fn call_site ( ) -> Span {
250
+ Bridge :: with ( |bridge| bridge. context . call_site )
251
+ }
252
+
253
+ pub ( crate ) fn mixed_site ( ) -> Span {
254
+ Bridge :: with ( |bridge| bridge. context . mixed_site )
255
+ }
256
+ }
257
+
244
258
impl fmt:: Debug for Span {
245
259
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
246
260
f. write_str ( & self . debug ( ) )
@@ -274,6 +288,21 @@ macro_rules! define_client_side {
274
288
}
275
289
with_api ! ( self , self , define_client_side) ;
276
290
291
+ struct Bridge < ' a > {
292
+ /// Reusable buffer (only `clear`-ed, never shrunk), primarily
293
+ /// used for making requests.
294
+ cached_buffer : Buffer ,
295
+
296
+ /// Server-side function that the client uses to make requests.
297
+ dispatch : closure:: Closure < ' a , Buffer , Buffer > ,
298
+
299
+ /// Provided context for this macro expansion.
300
+ context : ExpnContext < Span > ,
301
+ }
302
+
303
+ impl < ' a > !Send for Bridge < ' a > { }
304
+ impl < ' a > !Sync for Bridge < ' a > { }
305
+
277
306
enum BridgeState < ' a > {
278
307
/// No server is currently connected to this client.
279
308
NotConnected ,
@@ -316,34 +345,6 @@ impl BridgeState<'_> {
316
345
}
317
346
318
347
impl Bridge < ' _ > {
319
- pub ( crate ) fn is_available ( ) -> bool {
320
- BridgeState :: with ( |state| match state {
321
- BridgeState :: Connected ( _) | BridgeState :: InUse => true ,
322
- BridgeState :: NotConnected => false ,
323
- } )
324
- }
325
-
326
- fn enter < R > ( self , f : impl FnOnce ( ) -> R ) -> R {
327
- let force_show_panics = self . force_show_panics ;
328
- // Hide the default panic output within `proc_macro` expansions.
329
- // NB. the server can't do this because it may use a different libstd.
330
- static HIDE_PANICS_DURING_EXPANSION : Once = Once :: new ( ) ;
331
- HIDE_PANICS_DURING_EXPANSION . call_once ( || {
332
- let prev = panic:: take_hook ( ) ;
333
- panic:: set_hook ( Box :: new ( move |info| {
334
- let show = BridgeState :: with ( |state| match state {
335
- BridgeState :: NotConnected => true ,
336
- BridgeState :: Connected ( _) | BridgeState :: InUse => force_show_panics,
337
- } ) ;
338
- if show {
339
- prev ( info)
340
- }
341
- } ) ) ;
342
- } ) ;
343
-
344
- BRIDGE_STATE . with ( |state| state. set ( BridgeState :: Connected ( self ) , f) )
345
- }
346
-
347
348
fn with < R > ( f : impl FnOnce ( & mut Bridge < ' _ > ) -> R ) -> R {
348
349
BridgeState :: with ( |state| match state {
349
350
BridgeState :: NotConnected => {
@@ -357,6 +358,13 @@ impl Bridge<'_> {
357
358
}
358
359
}
359
360
361
+ pub ( crate ) fn is_available ( ) -> bool {
362
+ BridgeState :: with ( |state| match state {
363
+ BridgeState :: Connected ( _) | BridgeState :: InUse => true ,
364
+ BridgeState :: NotConnected => false ,
365
+ } )
366
+ }
367
+
360
368
/// A client-side RPC entry-point, which may be using a different `proc_macro`
361
369
/// from the one used by the server, but can be invoked compatibly.
362
370
///
@@ -374,7 +382,7 @@ pub struct Client<I, O> {
374
382
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
375
383
pub ( super ) get_handle_counters : extern "C" fn ( ) -> & ' static HandleCounters ,
376
384
377
- pub ( super ) run : extern "C" fn ( Bridge < ' _ > ) -> Buffer ,
385
+ pub ( super ) run : extern "C" fn ( BridgeConfig < ' _ > ) -> Buffer ,
378
386
379
387
pub ( super ) _marker : PhantomData < fn ( I ) -> O > ,
380
388
}
@@ -386,40 +394,62 @@ impl<I, O> Clone for Client<I, O> {
386
394
}
387
395
}
388
396
397
+ fn maybe_install_panic_hook ( force_show_panics : bool ) {
398
+ // Hide the default panic output within `proc_macro` expansions.
399
+ // NB. the server can't do this because it may use a different libstd.
400
+ static HIDE_PANICS_DURING_EXPANSION : Once = Once :: new ( ) ;
401
+ HIDE_PANICS_DURING_EXPANSION . call_once ( || {
402
+ let prev = panic:: take_hook ( ) ;
403
+ panic:: set_hook ( Box :: new ( move |info| {
404
+ let show = BridgeState :: with ( |state| match state {
405
+ BridgeState :: NotConnected => true ,
406
+ BridgeState :: Connected ( _) | BridgeState :: InUse => force_show_panics,
407
+ } ) ;
408
+ if show {
409
+ prev ( info)
410
+ }
411
+ } ) ) ;
412
+ } ) ;
413
+ }
414
+
389
415
/// Client-side helper for handling client panics, entering the bridge,
390
416
/// deserializing input and serializing output.
391
417
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
392
418
fn run_client < A : for < ' a , ' s > DecodeMut < ' a , ' s , ( ) > , R : Encode < ( ) > > (
393
- mut bridge : Bridge < ' _ > ,
419
+ config : BridgeConfig < ' _ > ,
394
420
f : impl FnOnce ( A ) -> R ,
395
421
) -> Buffer {
396
- // The initial `cached_buffer` contains the input.
397
- let mut buf = bridge. cached_buffer . take ( ) ;
422
+ let BridgeConfig { input : mut buf, dispatch, force_show_panics, .. } = config;
398
423
399
424
panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
400
- bridge. enter ( || {
401
- let reader = & mut & buf[ ..] ;
402
- let input = A :: decode ( reader, & mut ( ) ) ;
403
-
404
- // Put the `cached_buffer` back in the `Bridge`, for requests.
405
- Bridge :: with ( |bridge| bridge. cached_buffer = buf. take ( ) ) ;
406
-
407
- let output = f ( input) ;
408
-
409
- // Take the `cached_buffer` back out, for the output value.
410
- buf = Bridge :: with ( |bridge| bridge. cached_buffer . take ( ) ) ;
411
-
412
- // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
413
- // from encoding a panic (`Err(e: PanicMessage)`) to avoid
414
- // having handles outside the `bridge.enter(|| ...)` scope, and
415
- // to catch panics that could happen while encoding the success.
416
- //
417
- // Note that panics should be impossible beyond this point, but
418
- // this is defensively trying to avoid any accidental panicking
419
- // reaching the `extern "C"` (which should `abort` but might not
420
- // at the moment, so this is also potentially preventing UB).
421
- buf. clear ( ) ;
422
- Ok :: < _ , ( ) > ( output) . encode ( & mut buf, & mut ( ) ) ;
425
+ maybe_install_panic_hook ( force_show_panics) ;
426
+
427
+ let reader = & mut & buf[ ..] ;
428
+ let ( input, context) = <( A , ExpnContext < Span > ) >:: decode ( reader, & mut ( ) ) ;
429
+
430
+ // Put the buffer we used for input back in the `Bridge` for requests.
431
+ let new_state =
432
+ BridgeState :: Connected ( Bridge { cached_buffer : buf. take ( ) , dispatch, context } ) ;
433
+
434
+ BRIDGE_STATE . with ( |state| {
435
+ state. set ( new_state, || {
436
+ let output = f ( input) ;
437
+
438
+ // Take the `cached_buffer` back out, for the output value.
439
+ buf = Bridge :: with ( |bridge| bridge. cached_buffer . take ( ) ) ;
440
+
441
+ // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
442
+ // from encoding a panic (`Err(e: PanicMessage)`) to avoid
443
+ // having handles outside the `bridge.enter(|| ...)` scope, and
444
+ // to catch panics that could happen while encoding the success.
445
+ //
446
+ // Note that panics should be impossible beyond this point, but
447
+ // this is defensively trying to avoid any accidental panicking
448
+ // reaching the `extern "C"` (which should `abort` but might not
449
+ // at the moment, so this is also potentially preventing UB).
450
+ buf. clear ( ) ;
451
+ Ok :: < _ , ( ) > ( output) . encode ( & mut buf, & mut ( ) ) ;
452
+ } )
423
453
} )
424
454
} ) )
425
455
. map_err ( PanicMessage :: from)
0 commit comments