@@ -187,7 +187,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
187
187
f : F ,
188
188
) -> R {
189
189
use rustc_data_structures:: { jobserver, sync:: FromDyn } ;
190
- use rustc_middle:: ty:: tls;
190
+ use rustc_middle:: ty:: tls:: { self , GcxPtr } ;
191
191
use rustc_query_impl:: QueryCtxt ;
192
192
use rustc_query_system:: query:: { deadlock, QueryContext } ;
193
193
@@ -210,18 +210,34 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
210
210
. deadlock_handler ( || {
211
211
// On deadlock, creates a new thread and forwards information in thread
212
212
// locals to it. The new thread runs the deadlock handler.
213
- let query_map = FromDyn :: from ( tls:: with ( |tcx| {
214
- QueryCtxt :: new ( tcx)
215
- . try_collect_active_jobs ( )
216
- . expect ( "active jobs shouldn't be locked in deadlock handler" )
217
- } ) ) ;
213
+ let query_map = FromDyn :: from ( {
214
+ // Get a GlobalCtxt reference from GCX_PTR as we cannot rely on having a TyCtxt TLS
215
+ // reference here.
216
+ // SAFETY: No thread will end the lifetime of `GlobalCtxt` as they're deadlocked
217
+ // and won't resume until the `deadlock` call.
218
+ unsafe {
219
+ tls:: GCX_PTR . with ( |gcx_ptr| {
220
+ gcx_ptr. access ( |gcx| {
221
+ tls:: enter_context ( & tls:: ImplicitCtxt :: new ( gcx) , || {
222
+ tls:: with ( |tcx| {
223
+ QueryCtxt :: new ( tcx) . try_collect_active_jobs ( ) . expect (
224
+ "active jobs shouldn't be locked in deadlock handler" ,
225
+ )
226
+ } )
227
+ } )
228
+ } )
229
+ } )
230
+ }
231
+ } ) ;
218
232
let registry = rayon_core:: Registry :: current ( ) ;
219
233
thread:: spawn ( move || deadlock ( query_map. into_inner ( ) , & registry) ) ;
220
234
} ) ;
221
235
if let Some ( size) = get_stack_size ( ) {
222
236
builder = builder. stack_size ( size) ;
223
237
}
224
238
239
+ let gcx_ptr = GcxPtr :: new ( ) ;
240
+
225
241
// We create the session globals on the main thread, then create the thread
226
242
// pool. Upon creation, each worker thread created gets a copy of the
227
243
// session globals in TLS. This is possible because `SessionGlobals` impls
@@ -237,7 +253,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
237
253
registry. register ( ) ;
238
254
239
255
rustc_span:: set_session_globals_then ( session_globals. into_inner ( ) , || {
240
- thread. run ( )
256
+ tls :: GCX_PTR . set ( & gcx_ptr , || thread. run ( ) )
241
257
} )
242
258
} ,
243
259
// Run `f` on the first thread in the thread pool.
0 commit comments