Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --code from glacier <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: NOTE this is the alt master rustc, installed via <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
This features a parallel-compiler-only bug. It is a variant of It is ultimately a blocker for and might be a blocker for but itself does not need to be fixed any time soon.
Remark from
This is not a problem with the implementation logic of the deadlock handler, but a very hard-to-trace thread scheduling vulnerability. If we add the following non-functional statement in of the function, this problem will disappear. Get rid of in deadlock handler can fix this. I just submited a to fix a set of ui test failures, including this issue.

Discussion:
use rustc_middle::ty::tls; use rustc_parse::validate_attr; #[cfg(parallel_compiler)] <del> use rustc_query_impl::QueryCtxt; </del> <ins> use rustc_query_impl::{QueryContext, QueryCtxt}; </ins> use rustc_session as session; use rustc_session::config::CheckCfg; use rustc_session::config::{self, CrateType};

unsafe fn handle_deadlock() { let registry = rustc_rayon_core::Registry::current(); <del> let context = tls::get_tlv(); assert!(context != 0); rustc_data_structures::sync::assert_sync::<tls::ImplicitCtxt<'_, '_>>(); let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>); let session_globals = rustc_span::with_session_globals(|sg| sg as *const _); let session_globals = &*session_globals; thread::spawn(move || { tls::enter_context(icx, |_| { rustc_span::set_session_globals_then(session_globals, || { tls::with(|tcx| QueryCtxt::from_tcx(tcx).deadlock(&registry)) }) }); </del> <ins> let query_map = tls::with(|tcx| { QueryCtxt::from_tcx(tcx) .try_collect_active_jobs() .expect("active jobs shouldn't be locked in deadlock handler") </ins> }); <ins> thread::spawn(move || rustc_query_impl::deadlock(query_map, &registry)); </ins> } #[cfg(parallel_compiler)]

mod plumbing; pub use plumbing::QueryCtxt; use rustc_query_system::query::*; <ins> #[cfg(parallel_compiler)] pub use rustc_query_system::query::{deadlock, QueryContext}; </ins> mod keys; use keys::Key;

self.queries.on_disk_cache.as_ref() } <del> #[cfg(parallel_compiler)] pub unsafe fn deadlock(self, registry: &rustc_rayon_core::Registry) { rustc_query_system::query::deadlock(self, registry) } </del> pub(super) fn encode_query_results( self, encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,

/// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. #[cfg(parallel_compiler)] <del> pub fn deadlock<CTX: QueryContext>(tcx: CTX, registry: &rayon_core::Registry) { </del> <ins> pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { </ins> let on_panic = OnDrop(|| { eprintln!("deadlock handler panicked, aborting process"); process::abort(); }); let mut wakelist = Vec::new(); <del> let query_map = tcx.try_collect_active_jobs().unwrap(); </del> let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect(); let mut found_cycle = false;