@@ -185,7 +185,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
185185 f : F ,
186186) -> R {
187187 use rustc_data_structures:: { jobserver, sync:: FromDyn } ;
188- use rustc_middle:: ty:: tls;
188+ use rustc_middle:: ty:: tls:: { self , GcxPtr } ;
189189 use rustc_query_impl:: QueryCtxt ;
190190 use rustc_query_system:: query:: { deadlock, QueryContext } ;
191191
@@ -208,18 +208,34 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
208208 . deadlock_handler ( || {
209209 // On deadlock, creates a new thread and forwards information in thread
210210 // 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+ } ) ;
216230 let registry = rayon_core:: Registry :: current ( ) ;
217231 thread:: spawn ( move || deadlock ( query_map. into_inner ( ) , & registry) ) ;
218232 } ) ;
219233 if let Some ( size) = get_stack_size ( ) {
220234 builder = builder. stack_size ( size) ;
221235 }
222236
237+ let gcx_ptr = GcxPtr :: new ( ) ;
238+
223239 // We create the session globals on the main thread, then create the thread
224240 // pool. Upon creation, each worker thread created gets a copy of the
225241 // 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>(
235251 registry. register ( ) ;
236252
237253 rustc_span:: set_session_globals_then ( session_globals. into_inner ( ) , || {
238- thread. run ( )
254+ tls :: GCX_PTR . set ( & gcx_ptr , || thread. run ( ) )
239255 } )
240256 } ,
241257 // Run `f` on the first thread in the thread pool.
0 commit comments