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