22
33use super :: * ;
44
5+ use std:: cell:: Cell ;
56use std:: marker:: PhantomData ;
67
78macro_rules! define_handles {
@@ -256,7 +257,7 @@ macro_rules! define_client_side {
256257 api_tags:: Method :: $name( api_tags:: $name:: $method) . encode( & mut b, & mut ( ) ) ;
257258 reverse_encode!( b; $( $arg) ,* ) ;
258259
259- b = bridge. dispatch. call ( b) ;
260+ b = ( bridge. dispatch) ( b) ;
260261
261262 let r = Result :: <_, PanicMessage >:: decode( & mut & b[ ..] , & mut ( ) ) ;
262263
@@ -270,48 +271,64 @@ macro_rules! define_client_side {
270271}
271272with_api ! ( self , self , define_client_side) ;
272273
273- enum BridgeState < ' a > {
274+ enum BridgeState {
274275 /// No server is currently connected to this client.
275276 NotConnected ,
276277
277278 /// A server is connected and available for requests.
278- Connected ( Bridge < ' a > ) ,
279+ Connected ( Bridge ) ,
279280
280281 /// Access to the bridge is being exclusively acquired
281282 /// (e.g., during `BridgeState::with`).
282283 InUse ,
283284}
284285
285- enum BridgeStateL { }
286+ impl BridgeState {
287+ /// Sets the thread-local `BridgeState` to `replacement` while
288+ /// running `f`, which gets the old `BridgeState`, mutably.
289+ ///
290+ /// The state will be restored after `f` exits, even
291+ /// by panic, including modifications made to it by `f`.
292+ fn replace_during < R > ( replacement : Self , f : impl FnOnce ( & mut Self ) -> R ) -> R {
293+ /// Wrapper that ensures that a cell always gets filled
294+ /// (with the original state, optionally changed by `f`),
295+ /// even if `f` had panicked.
296+ struct PutBackOnDrop < ' a , T > {
297+ cell : & ' a Cell < T > ,
298+ value : Option < T > ,
299+ }
286300
287- impl < ' a > scoped_cell:: ApplyL < ' a > for BridgeStateL {
288- type Out = BridgeState < ' a > ;
289- }
301+ impl < ' a , T > Drop for PutBackOnDrop < ' a , T > {
302+ fn drop ( & mut self ) {
303+ self . cell . set ( self . value . take ( ) . unwrap ( ) ) ;
304+ }
305+ }
290306
291- thread_local ! {
292- static BRIDGE_STATE : scoped_cell:: ScopedCell <BridgeStateL > =
293- scoped_cell:: ScopedCell :: new( BridgeState :: NotConnected ) ;
294- }
307+ thread_local ! {
308+ static BRIDGE_STATE : Cell <BridgeState > = Cell :: new( BridgeState :: NotConnected ) ;
309+ }
310+ BRIDGE_STATE . with ( |state| {
311+ let mut put_back_on_drop =
312+ PutBackOnDrop { cell : state, value : Some ( state. replace ( replacement) ) } ;
313+
314+ f ( put_back_on_drop. value . as_mut ( ) . unwrap ( ) )
315+ } )
316+ }
295317
296- impl BridgeState < ' _ > {
297318 /// Take exclusive control of the thread-local
298319 /// `BridgeState`, and pass it to `f`, mutably.
320+ ///
299321 /// The state will be restored after `f` exits, even
300322 /// by panic, including modifications made to it by `f`.
301323 ///
302324 /// N.B., while `f` is running, the thread-local state
303325 /// is `BridgeState::InUse`.
304- fn with < R > ( f : impl FnOnce ( & mut BridgeState < ' _ > ) -> R ) -> R {
305- BRIDGE_STATE . with ( |state| {
306- state. replace ( BridgeState :: InUse , |mut state| {
307- // FIXME(#52812) pass `f` directly to `replace` when `RefMutL` is gone
308- f ( & mut * state)
309- } )
310- } )
326+ fn with < R > ( f : impl FnOnce ( & mut Self ) -> R ) -> R {
327+ Self :: replace_during ( BridgeState :: InUse , f)
311328 }
312329}
313330
314- impl Bridge < ' _ > {
331+ impl Bridge {
315332 pub ( crate ) fn is_available ( ) -> bool {
316333 BridgeState :: with ( |state| match state {
317334 BridgeState :: Connected ( _) | BridgeState :: InUse => true ,
@@ -337,10 +354,10 @@ impl Bridge<'_> {
337354 } ) ) ;
338355 } ) ;
339356
340- BRIDGE_STATE . with ( |state| state . set ( BridgeState :: Connected ( self ) , f ) )
357+ BridgeState :: replace_during ( BridgeState :: Connected ( self ) , |_| f ( ) )
341358 }
342359
343- fn with < R > ( f : impl FnOnce ( & mut Bridge < ' _ > ) -> R ) -> R {
360+ fn with < R > ( f : impl FnOnce ( & mut Self ) -> R ) -> R {
344361 BridgeState :: with ( |state| match state {
345362 BridgeState :: NotConnected => {
346363 panic ! ( "procedural macro API is used outside of a procedural macro" ) ;
@@ -367,15 +384,15 @@ pub struct Client<F> {
367384 // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
368385 // a wrapper `fn` pointer, once `const fn` can reference `static`s.
369386 pub ( super ) get_handle_counters : extern "C" fn ( ) -> & ' static HandleCounters ,
370- pub ( super ) run : extern "C" fn ( Bridge < ' _ > , F ) -> Buffer < u8 > ,
387+ pub ( super ) run : extern "C" fn ( Bridge , F ) -> Buffer < u8 > ,
371388 pub ( super ) f : F ,
372389}
373390
374391/// Client-side helper for handling client panics, entering the bridge,
375392/// deserializing input and serializing output.
376393// FIXME(eddyb) maybe replace `Bridge::enter` with this?
377394fn run_client < A : for < ' a , ' s > DecodeMut < ' a , ' s , ( ) > , R : Encode < ( ) > > (
378- mut bridge : Bridge < ' _ > ,
395+ mut bridge : Bridge ,
379396 f : impl FnOnce ( A ) -> R ,
380397) -> Buffer < u8 > {
381398 // The initial `cached_buffer` contains the input.
@@ -418,7 +435,7 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
418435impl Client < fn ( crate :: TokenStream ) -> crate :: TokenStream > {
419436 pub const fn expand1 ( f : fn ( crate :: TokenStream ) -> crate :: TokenStream ) -> Self {
420437 extern "C" fn run (
421- bridge : Bridge < ' _ > ,
438+ bridge : Bridge ,
422439 f : impl FnOnce ( crate :: TokenStream ) -> crate :: TokenStream ,
423440 ) -> Buffer < u8 > {
424441 run_client ( bridge, |input| f ( crate :: TokenStream ( input) ) . 0 )
@@ -432,7 +449,7 @@ impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
432449 f : fn ( crate :: TokenStream , crate :: TokenStream ) -> crate :: TokenStream ,
433450 ) -> Self {
434451 extern "C" fn run (
435- bridge : Bridge < ' _ > ,
452+ bridge : Bridge ,
436453 f : impl FnOnce ( crate :: TokenStream , crate :: TokenStream ) -> crate :: TokenStream ,
437454 ) -> Buffer < u8 > {
438455 run_client ( bridge, |( input, input2) | {
0 commit comments