1
Fork 0

Auto merge of #107586 - SparrowLii:parallel-query, r=cjgillot

Introduce `DynSend` and `DynSync` auto trait for parallel compiler

part of parallel-rustc #101566

This PR introduces `DynSend / DynSync` trait and `FromDyn / IntoDyn` structure in rustc_data_structure::marker. `FromDyn` can dynamically check data structures for thread safety when switching to parallel environments (such as calling `par_for_each_in`). This happens only when `-Z threads > 1` so it doesn't affect single-threaded mode's compile efficiency.

r? `@cjgillot`
This commit is contained in:
bors 2023-05-13 13:47:53 +00:00
commit dd8ec9c88d
26 changed files with 557 additions and 110 deletions

View file

@ -5,7 +5,7 @@ use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
@ -150,11 +150,6 @@ impl<'hir> Map<'hir> {
self.tcx.hir_module_items(module).items()
}
#[inline]
pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
}
pub fn def_key(self, def_id: LocalDefId) -> DefKey {
// Accessing the DefKey is ok, since it is part of DefPathHash.
self.tcx.definitions_untracked().def_key(def_id)
@ -502,7 +497,7 @@ impl<'hir> Map<'hir> {
}
#[inline]
pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) {
pub fn par_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
}
@ -640,7 +635,7 @@ impl<'hir> Map<'hir> {
}
#[inline]
pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) {
pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
let crate_items = self.tcx.hir_crate_items(());
par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id))
}

View file

@ -9,7 +9,7 @@ pub mod place;
use crate::ty::query::Providers;
use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::*;
use rustc_query_system::ich::StableHashingContext;
@ -77,19 +77,19 @@ impl ModuleItems {
self.owners().map(|id| id.def_id)
}
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
par_for_each_in(&self.items[..], |&id| f(id))
}
pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) {
pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) {
par_for_each_in(&self.trait_items[..], |&id| f(id))
}
pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) {
pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) {
par_for_each_in(&self.impl_items[..], |&id| f(id))
}
pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) {
pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) {
par_for_each_in(&self.foreign_items[..], |&id| f(id))
}
}

View file

@ -496,7 +496,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<dyn Any + sync::Sync + sync::Send>,
pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
pub dep_graph: DepGraph,
@ -648,7 +648,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// reference to the context, to allow formatting values that need it.
pub fn create_global_ctxt(
s: &'tcx Session,
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
untracked: Untracked,

View file

@ -94,8 +94,8 @@ where
f(None)
} else {
// We could get an `ImplicitCtxt` pointer from another thread.
// Ensure that `ImplicitCtxt` is `Sync`.
sync::assert_sync::<ImplicitCtxt<'_, '_>>();
// Ensure that `ImplicitCtxt` is `DynSync`.
sync::assert_dyn_sync::<ImplicitCtxt<'_, '_>>();
unsafe { f(Some(downcast(context))) }
}

View file

@ -199,6 +199,12 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
unsafe impl<T: Sync> Sync for List<T> {}
// We need this since `List` uses extern type `OpaqueListContents`.
#[cfg(parallel_compiler)]
use rustc_data_structures::sync::DynSync;
#[cfg(parallel_compiler)]
unsafe impl<T: DynSync> DynSync for List<T> {}
// Safety:
// Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
// thus aligns of `Equivalent<T>` and `List<T>` must be the same.