@@ -222,6 +222,20 @@ impl Clone for SourceFile {
222
222
}
223
223
}
224
224
225
+ impl Span {
226
+ pub ( crate ) fn def_site ( ) -> Span {
227
+ Bridge :: with ( |bridge| bridge. context . def_site )
228
+ }
229
+
230
+ pub ( crate ) fn call_site ( ) -> Span {
231
+ Bridge :: with ( |bridge| bridge. context . call_site )
232
+ }
233
+
234
+ pub ( crate ) fn mixed_site ( ) -> Span {
235
+ Bridge :: with ( |bridge| bridge. context . mixed_site )
236
+ }
237
+ }
238
+
225
239
impl fmt:: Debug for Span {
226
240
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
227
241
f. write_str ( & self . debug ( ) )
@@ -255,6 +269,21 @@ macro_rules! define_client_side {
255
269
}
256
270
with_api ! ( self , self , define_client_side) ;
257
271
272
+ struct Bridge < ' a > {
273
+ /// Reusable buffer (only `clear`-ed, never shrunk), primarily
274
+ /// used for making requests.
275
+ cached_buffer : Buffer < u8 > ,
276
+
277
+ /// Server-side function that the client uses to make requests.
278
+ dispatch : closure:: Closure < ' a , Buffer < u8 > , Buffer < u8 > > ,
279
+
280
+ /// Provided context for this macro expansion.
281
+ context : ExpnContext < Span > ,
282
+ }
283
+
284
+ impl < ' a > !Send for Bridge < ' a > { }
285
+ impl < ' a > !Sync for Bridge < ' a > { }
286
+
258
287
enum BridgeState < ' a > {
259
288
/// No server is currently connected to this client.
260
289
NotConnected ,
@@ -297,34 +326,6 @@ impl BridgeState<'_> {
297
326
}
298
327
299
328
impl Bridge < ' _ > {
300
- pub ( crate ) fn is_available ( ) -> bool {
301
- BridgeState :: with ( |state| match state {
302
- BridgeState :: Connected ( _) | BridgeState :: InUse => true ,
303
- BridgeState :: NotConnected => false ,
304
- } )
305
- }
306
-
307
- fn enter < R > ( self , f : impl FnOnce ( ) -> R ) -> R {
308
- let force_show_panics = self . force_show_panics ;
309
- // Hide the default panic output within `proc_macro` expansions.
310
- // NB. the server can't do this because it may use a different libstd.
311
- static HIDE_PANICS_DURING_EXPANSION : Once = Once :: new ( ) ;
312
- HIDE_PANICS_DURING_EXPANSION . call_once ( || {
313
- let prev = panic:: take_hook ( ) ;
314
- panic:: set_hook ( Box :: new ( move |info| {
315
- let show = BridgeState :: with ( |state| match state {
316
- BridgeState :: NotConnected => true ,
317
- BridgeState :: Connected ( _) | BridgeState :: InUse => force_show_panics,
318
- } ) ;
319
- if show {
320
- prev ( info)
321
- }
322
- } ) ) ;
323
- } ) ;
324
-
325
- BRIDGE_STATE . with ( |state| state. set ( BridgeState :: Connected ( self ) , f) )
326
- }
327
-
328
329
fn with < R > ( f : impl FnOnce ( & mut Bridge < ' _ > ) -> R ) -> R {
329
330
BridgeState :: with ( |state| match state {
330
331
BridgeState :: NotConnected => {
@@ -338,6 +339,13 @@ impl Bridge<'_> {
338
339
}
339
340
}
340
341
342
+ pub ( crate ) fn is_available ( ) -> bool {
343
+ BridgeState :: with ( |state| match state {
344
+ BridgeState :: Connected ( _) | BridgeState :: InUse => true ,
345
+ BridgeState :: NotConnected => false ,
346
+ } )
347
+ }
348
+
341
349
/// A client-side "global object" (usually a function pointer),
342
350
/// which may be using a different `proc_macro` from the one
343
351
/// used by the server, but can be interacted with compatibly.
@@ -352,44 +360,66 @@ pub struct Client<F> {
352
360
// FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
353
361
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
354
362
pub ( super ) get_handle_counters : extern "C" fn ( ) -> & ' static HandleCounters ,
355
- pub ( super ) run : extern "C" fn ( Bridge < ' _ > , F ) -> Buffer < u8 > ,
363
+ pub ( super ) run : extern "C" fn ( BridgeConfig < ' _ > , F ) -> Buffer < u8 > ,
356
364
pub ( super ) f : F ,
357
365
}
358
366
367
+ fn maybe_install_panic_hook ( force_show_panics : bool ) {
368
+ // Hide the default panic output within `proc_macro` expansions.
369
+ // NB. the server can't do this because it may use a different libstd.
370
+ static HIDE_PANICS_DURING_EXPANSION : Once = Once :: new ( ) ;
371
+ HIDE_PANICS_DURING_EXPANSION . call_once ( || {
372
+ let prev = panic:: take_hook ( ) ;
373
+ panic:: set_hook ( Box :: new ( move |info| {
374
+ let show = BridgeState :: with ( |state| match state {
375
+ BridgeState :: NotConnected => true ,
376
+ BridgeState :: Connected ( _) | BridgeState :: InUse => force_show_panics,
377
+ } ) ;
378
+ if show {
379
+ prev ( info)
380
+ }
381
+ } ) ) ;
382
+ } ) ;
383
+ }
384
+
359
385
/// Client-side helper for handling client panics, entering the bridge,
360
386
/// deserializing input and serializing output.
361
387
// FIXME(eddyb) maybe replace `Bridge::enter` with this?
362
388
fn run_client < A : for < ' a , ' s > DecodeMut < ' a , ' s , ( ) > , R : Encode < ( ) > > (
363
- mut bridge : Bridge < ' _ > ,
389
+ config : BridgeConfig < ' _ > ,
364
390
f : impl FnOnce ( A ) -> R ,
365
391
) -> Buffer < u8 > {
366
- // The initial `cached_buffer` contains the input.
367
- let mut b = bridge. cached_buffer . take ( ) ;
392
+ let BridgeConfig { input : mut b, dispatch, force_show_panics } = config;
368
393
369
394
panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
370
- bridge. enter ( || {
371
- let reader = & mut & b[ ..] ;
372
- let input = A :: decode ( reader, & mut ( ) ) ;
373
-
374
- // Put the `cached_buffer` back in the `Bridge`, for requests.
375
- Bridge :: with ( |bridge| bridge. cached_buffer = b. take ( ) ) ;
376
-
377
- let output = f ( input) ;
378
-
379
- // Take the `cached_buffer` back out, for the output value.
380
- b = Bridge :: with ( |bridge| bridge. cached_buffer . take ( ) ) ;
381
-
382
- // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
383
- // from encoding a panic (`Err(e: PanicMessage)`) to avoid
384
- // having handles outside the `bridge.enter(|| ...)` scope, and
385
- // to catch panics that could happen while encoding the success.
386
- //
387
- // Note that panics should be impossible beyond this point, but
388
- // this is defensively trying to avoid any accidental panicking
389
- // reaching the `extern "C"` (which should `abort` but may not
390
- // at the moment, so this is also potentially preventing UB).
391
- b. clear ( ) ;
392
- Ok :: < _ , ( ) > ( output) . encode ( & mut b, & mut ( ) ) ;
395
+ maybe_install_panic_hook ( force_show_panics) ;
396
+
397
+ let reader = & mut & b[ ..] ;
398
+ let ( input, context) = <( A , ExpnContext < Span > ) >:: decode ( reader, & mut ( ) ) ;
399
+
400
+ // Put the buffer we used for input back in the `Bridge` for requests.
401
+ let new_state =
402
+ BridgeState :: Connected ( Bridge { cached_buffer : b. take ( ) , dispatch, context } ) ;
403
+
404
+ BRIDGE_STATE . with ( |state| {
405
+ state. set ( new_state, || {
406
+ let output = f ( input) ;
407
+
408
+ // Take the `cached_buffer` back out, for the output value.
409
+ b = Bridge :: with ( |bridge| bridge. cached_buffer . take ( ) ) ;
410
+
411
+ // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
412
+ // from encoding a panic (`Err(e: PanicMessage)`) to avoid
413
+ // having handles outside the `bridge.enter(|| ...)` scope, and
414
+ // to catch panics that could happen while encoding the success.
415
+ //
416
+ // Note that panics should be impossible beyond this point, but
417
+ // this is defensively trying to avoid any accidental panicking
418
+ // reaching the `extern "C"` (which should `abort` but may not
419
+ // at the moment, so this is also potentially preventing UB).
420
+ b. clear ( ) ;
421
+ Ok :: < _ , ( ) > ( output) . encode ( & mut b, & mut ( ) ) ;
422
+ } )
393
423
} )
394
424
} ) )
395
425
. map_err ( PanicMessage :: from)
@@ -404,7 +434,7 @@ impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
404
434
#[ rustc_allow_const_fn_unstable( const_fn) ]
405
435
pub const fn expand1 ( f : fn ( crate :: TokenStream ) -> crate :: TokenStream ) -> Self {
406
436
extern "C" fn run (
407
- bridge : Bridge < ' _ > ,
437
+ bridge : BridgeConfig < ' _ > ,
408
438
f : impl FnOnce ( crate :: TokenStream ) -> crate :: TokenStream ,
409
439
) -> Buffer < u8 > {
410
440
run_client ( bridge, |input| f ( crate :: TokenStream ( input) ) . 0 )
@@ -419,7 +449,7 @@ impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
419
449
f : fn ( crate :: TokenStream , crate :: TokenStream ) -> crate :: TokenStream ,
420
450
) -> Self {
421
451
extern "C" fn run (
422
- bridge : Bridge < ' _ > ,
452
+ bridge : BridgeConfig < ' _ > ,
423
453
f : impl FnOnce ( crate :: TokenStream , crate :: TokenStream ) -> crate :: TokenStream ,
424
454
) -> Buffer < u8 > {
425
455
run_client ( bridge, |( input, input2) | {
0 commit comments