@@ -187,7 +187,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
187187 f : F ,
188188) -> R {
189189 use rustc_data_structures:: { jobserver, sync:: FromDyn } ;
190- use rustc_middle:: ty:: tls;
190+ use rustc_middle:: ty:: tls:: { self , GcxPtr } ;
191191 use rustc_query_impl:: QueryCtxt ;
192192 use rustc_query_system:: query:: { deadlock, QueryContext } ;
193193
@@ -210,18 +210,34 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
210210 . deadlock_handler ( || {
211211 // On deadlock, creates a new thread and forwards information in thread
212212 // 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+ } ) ;
218232 let registry = rayon_core:: Registry :: current ( ) ;
219233 thread:: spawn ( move || deadlock ( query_map. into_inner ( ) , & registry) ) ;
220234 } ) ;
221235 if let Some ( size) = get_stack_size ( ) {
222236 builder = builder. stack_size ( size) ;
223237 }
224238
239+ let gcx_ptr = GcxPtr :: new ( ) ;
240+
225241 // We create the session globals on the main thread, then create the thread
226242 // pool. Upon creation, each worker thread created gets a copy of the
227243 // 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>(
237253 registry. register ( ) ;
238254
239255 rustc_span:: set_session_globals_then ( session_globals. into_inner ( ) , || {
240- thread. run ( )
256+ tls :: GCX_PTR . set ( & gcx_ptr , || thread. run ( ) )
241257 } )
242258 } ,
243259 // Run `f` on the first thread in the thread pool.
0 commit comments