@@ -12,7 +12,7 @@ use rustc_span::LocalExpnId;
1212use crate :: base:: ExtCtxt ;
1313use crate :: errors;
1414
15- pub ( super ) fn expand < ' tcx > (
15+ pub ( super ) fn provide_derive_macro_expansion < ' tcx > (
1616 tcx : TyCtxt < ' tcx > ,
1717 key : ( LocalExpnId , & ' tcx TokenStream ) ,
1818) -> Result < & ' tcx TokenStream , ( ) > {
@@ -51,7 +51,6 @@ pub(super) fn expand<'tcx>(
5151type CLIENT = pm:: bridge:: client:: Client < pm:: TokenStream , pm:: TokenStream > ;
5252
5353// based on rust/compiler/rustc_middle/src/ty/context/tls.rs
54- // #[cfg(not(parallel_compiler))]
5554thread_local ! {
5655 /// A thread local variable that stores a pointer to the current `CONTEXT`.
5756 static TLV : Cell <( * mut ( ) , Option <CLIENT >) > = const { Cell :: new( ( ptr:: null_mut( ) , None ) ) } ;
@@ -67,21 +66,29 @@ unsafe fn downcast<'a>(context: *mut ()) -> &'a mut ExtCtxt<'a> {
6766 unsafe { & mut * ( context as * mut ExtCtxt < ' a > ) }
6867}
6968
70- /// Sets `context` as the new current `CONTEXT` for the duration of the function `f`.
7169#[ inline]
72- pub fn enter_context < ' a , F , R > ( context : ( & mut ExtCtxt < ' a > , CLIENT ) , f : F ) -> R
70+ fn enter_context_erased < F , R > ( erased : ( * mut ( ) , Option < CLIENT > ) , f : F ) -> R
7371where
7472 F : FnOnce ( ) -> R ,
7573{
76- let ( ectx, client) = context;
77- let erased = ( erase ( ectx) , Some ( client) ) ;
7874 TLV . with ( |tlv| {
7975 let old = tlv. replace ( erased) ;
8076 let _reset = rustc_data_structures:: defer ( move || tlv. set ( old) ) ;
8177 f ( )
8278 } )
8379}
8480
81+ /// Sets `context` as the new current `CONTEXT` for the duration of the function `f`.
82+ #[ inline]
83+ pub fn enter_context < ' a , F , R > ( context : ( & mut ExtCtxt < ' a > , CLIENT ) , f : F ) -> R
84+ where
85+ F : FnOnce ( ) -> R ,
86+ {
87+ let ( ectx, client) = context;
88+ let erased = ( erase ( ectx) , Some ( client) ) ;
89+ enter_context_erased ( erased, f)
90+ }
91+
8592/// Allows access to the current `CONTEXT` in a closure if one is available.
8693#[ inline]
8794#[ track_caller]
@@ -98,7 +105,12 @@ where
98105 // TODO: we should not be able to?
99106 // sync::assert_dyn_sync::<CONTEXT<'_>>();
100107
101- unsafe { f ( Some ( & mut ( downcast ( ectx) , client_opt. unwrap ( ) ) ) ) }
108+ // prevent double entering, as that would allow creating two `&mut ExtCtxt`s
109+ // TODO: probably use a RefCell instead (which checks this properly)?
110+ enter_context_erased ( ( ptr:: null_mut ( ) , None ) , || unsafe {
111+ let ectx = downcast ( ectx) ;
112+ f ( Some ( & mut ( ectx, client_opt. unwrap ( ) ) ) )
113+ } )
102114 }
103115}
104116
0 commit comments