diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a05b2327f3a32..92b174daebf6e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -40,9 +40,9 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -#[cfg(parallel_compiler)] -use rustc_data_structures::sync::DynSend; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, RwLock, WorkerLocal}; +use rustc_data_structures::sync::{ + DynSend, DynSync, FreezeReadGuard, Lock, Lrc, RwLock, WorkerLocal, +}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -542,7 +542,7 @@ pub struct GlobalCtxt<'tcx> { /// /// FIXME(Centril): consider `dyn LintStoreMarker` once /// we can upcast to `Any` for some additional type safety. - pub lint_store: Lrc, + pub lint_store: Lrc, pub dep_graph: DepGraph, @@ -601,32 +601,22 @@ impl<'tcx> GlobalCtxt<'tcx> { { let icx = tls::ImplicitCtxt::new(self); - let gcx_ptr = - GcxPtr { value: Lrc::new(RwLock::new(Some(icx.tcx.gcx as *const _ as *const ()))) }; - - // Reset `gcx_ptr` to `None` when we exit. - let gcx_ptr_ = gcx_ptr.clone(); + // Reset `current_gcx` to `None` when we exit. let _on_drop = defer(move || { - *gcx_ptr_.value.write() = None; + *self.current_gcx.value.write() = None; }); // Set this `GlobalCtxt` as the current one. - *self.current_gcx.value.lock() = Some(gcx_ptr); + { + let mut guard = self.current_gcx.value.write(); + assert!(guard.is_none(), "no `GlobalCtxt` is currently set"); + *guard = Some(self as *const _ as *const ()); + } tls::enter_context(&icx, || f(icx.tcx)) } } -/// This stores a pointer to a `GlobalCtxt`. When the `GlobalCtxt` is no longer available the lock -/// will be set to `None`. -#[derive(Clone)] -struct GcxPtr { - value: Lrc>>, -} - -#[cfg(parallel_compiler)] -unsafe impl DynSend for GcxPtr {} - /// This is used to get a reference to a `GlobalCtxt` if one is available. /// /// This is needed to allow the deadlock handler access to `GlobalCtxt` to look for query cycles. @@ -635,21 +625,27 @@ unsafe impl DynSend for GcxPtr {} /// the deadlock handler is not called inside such a job. #[derive(Clone)] pub struct CurrentGcx { - value: Lrc>>, + /// This stores a pointer to a `GlobalCtxt`. This is set to `Some` inside `GlobalCtxt::enter` + /// and reset to `None` when that function returns or unwinds. + value: Lrc>>, } +#[cfg(parallel_compiler)] +unsafe impl DynSend for CurrentGcx {} +#[cfg(parallel_compiler)] +unsafe impl DynSync for CurrentGcx {} + impl CurrentGcx { pub fn new() -> Self { - Self { value: Lrc::new(Lock::new(None)) } + Self { value: Lrc::new(RwLock::new(None)) } } pub fn access(&self, f: impl for<'tcx> FnOnce(&'tcx GlobalCtxt<'tcx>) -> R) -> R { - let gcx_ptr = self.value.lock().clone().unwrap(); - let read_guard = gcx_ptr.value.read(); + let read_guard = self.value.read(); let gcx: *const GlobalCtxt<'_> = read_guard.unwrap() as *const _; - // SAFETY: We hold the read lock for `GcxPtr`. That prevents `GlobalCtxt::enter` from - // returning as it would first acquire the write lock. This ensures the `GlobalCtxt` is - // live during `f`. + // SAFETY: We hold the read lock for the `GlobalCtxt` pointer. That prevents + // `GlobalCtxt::enter` from returning as it would first acquire the write lock. + // This ensures the `GlobalCtxt` is live during `f`. f(unsafe { &*gcx }) } } @@ -755,7 +751,7 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, crate_types: Vec, stable_crate_id: StableCrateId, - lint_store: Lrc, + lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, untracked: Untracked,