@@ -12,7 +12,7 @@ use rustc_span::LocalExpnId;
12
12
use crate :: base:: ExtCtxt ;
13
13
use crate :: errors;
14
14
15
- pub ( super ) fn expand < ' tcx > (
15
+ pub ( super ) fn provide_derive_macro_expansion < ' tcx > (
16
16
tcx : TyCtxt < ' tcx > ,
17
17
key : ( LocalExpnId , & ' tcx TokenStream ) ,
18
18
) -> Result < & ' tcx TokenStream , ( ) > {
@@ -51,7 +51,6 @@ pub(super) fn expand<'tcx>(
51
51
type CLIENT = pm:: bridge:: client:: Client < pm:: TokenStream , pm:: TokenStream > ;
52
52
53
53
// based on rust/compiler/rustc_middle/src/ty/context/tls.rs
54
- // #[cfg(not(parallel_compiler))]
55
54
thread_local ! {
56
55
/// A thread local variable that stores a pointer to the current `CONTEXT`.
57
56
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> {
67
66
unsafe { & mut * ( context as * mut ExtCtxt < ' a > ) }
68
67
}
69
68
70
- /// Sets `context` as the new current `CONTEXT` for the duration of the function `f`.
71
69
#[ 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
73
71
where
74
72
F : FnOnce ( ) -> R ,
75
73
{
76
- let ( ectx, client) = context;
77
- let erased = ( erase ( ectx) , Some ( client) ) ;
78
74
TLV . with ( |tlv| {
79
75
let old = tlv. replace ( erased) ;
80
76
let _reset = rustc_data_structures:: defer ( move || tlv. set ( old) ) ;
81
77
f ( )
82
78
} )
83
79
}
84
80
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
+
85
92
/// Allows access to the current `CONTEXT` in a closure if one is available.
86
93
#[ inline]
87
94
#[ track_caller]
@@ -98,7 +105,12 @@ where
98
105
// TODO: we should not be able to?
99
106
// sync::assert_dyn_sync::<CONTEXT<'_>>();
100
107
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
+ } )
102
114
}
103
115
}
104
116
0 commit comments