提交 0bf7c2ad 编写于 作者: B bors

Auto merge of #70162 - cjgillot:split_query, r=Zoxc

Move the query system to a dedicated crate

The query system `rustc::ty::query` is split out into the `rustc_query_system` crate.

Some commits are unformatted, to ease rebasing.

Based on #67761 and #69910.

r? @Zoxc
......@@ -4081,12 +4081,12 @@ version = "0.0.0"
dependencies = [
"log",
"parking_lot 0.9.0",
"rustc_ast",
"rustc-rayon-core",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_span",
"serialize",
"smallvec 1.0.0",
]
......
......@@ -8,7 +8,6 @@
use rustc_hir::def_id::DefId;
mod dep_node;
mod safe;
pub(crate) use rustc_query_system::dep_graph::DepNodeParams;
pub use rustc_query_system::dep_graph::{
......@@ -17,8 +16,6 @@
};
pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt};
pub use safe::AssertDepGraphSafe;
pub use safe::DepGraphSafe;
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
......@@ -27,6 +24,8 @@
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
impl rustc_query_system::dep_graph::DepKind for DepKind {
const NULL: Self = DepKind::Null;
fn is_eval_always(&self) -> bool {
DepKind::is_eval_always(self)
}
......@@ -82,6 +81,10 @@ fn read_deps<OP>(op: OP) -> ()
op(icx.task_deps)
})
}
fn can_reconstruct_query_key(&self) -> bool {
DepKind::can_reconstruct_query_key(self)
}
}
impl<'tcx> DepContext for TyCtxt<'tcx> {
......@@ -92,6 +95,10 @@ fn create_stable_hashing_context(&self) -> Self::StableHashingContext {
TyCtxt::create_stable_hashing_context(*self)
}
fn debug_dep_tasks(&self) -> bool {
self.sess.opts.debugging_opts.dep_tasks
}
fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool {
// FIXME: This match is just a workaround for incremental bugs and should
// be removed. https://github.com/rust-lang/rust/issues/62649 is one such
......@@ -160,6 +167,14 @@ fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec<D
self.queries.on_disk_cache.store_diagnostics(dep_node_index, diagnostics)
}
fn store_diagnostics_for_anon_node(
&self,
dep_node_index: DepNodeIndex,
diagnostics: ThinVec<Diagnostic>,
) {
self.queries.on_disk_cache.store_diagnostics_for_anon_node(dep_node_index, diagnostics)
}
fn profiler(&self) -> &SelfProfilerRef {
&self.prof
}
......@@ -169,23 +184,3 @@ fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
def_id.index == hir_id.owner.local_def_index
}
impl rustc_query_system::HashStableContext for StableHashingContext<'_> {
fn debug_dep_tasks(&self) -> bool {
self.sess().opts.debugging_opts.dep_tasks
}
}
impl rustc_query_system::HashStableContextProvider<StableHashingContext<'tcx>> for TyCtxt<'tcx> {
fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> {
self.create_stable_hashing_context()
}
}
impl rustc_query_system::HashStableContextProvider<StableHashingContext<'a>>
for StableHashingContext<'a>
{
fn get_stable_hashing_context(&self) -> Self {
self.clone()
}
}
//! The `DepGraphSafe` trait
use crate::ty::TyCtxt;
pub use rustc_query_system::dep_graph::{AssertDepGraphSafe, DepGraphSafe};
/// The type context itself can be used to access all kinds of tracked
/// state, but those accesses should always generate read events.
impl<'tcx> DepGraphSafe for TyCtxt<'tcx> {}
......@@ -194,8 +194,6 @@ fn get_stable_hashing_context(&self) -> StableHashingContext<'a> {
}
}
impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {}
impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
panic!("Node IDs should not appear in incremental state");
......
......@@ -1603,7 +1603,7 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
pub mod tls {
use super::{ptr_eq, GlobalCtxt, TyCtxt};
use crate::dep_graph::TaskDeps;
use crate::dep_graph::{DepKind, TaskDeps};
use crate::ty::query;
use rustc_data_structures::sync::{self, Lock};
use rustc_data_structures::thin_vec::ThinVec;
......@@ -1630,7 +1630,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
/// The current query job, if any. This is updated by `JobOwner::start` in
/// `ty::query::plumbing` when executing a query.
pub query: Option<query::QueryJobId>,
pub query: Option<query::QueryJobId<DepKind>>,
/// Where to store diagnostics for the current query job, if any.
/// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
......
此差异已折叠。
......@@ -4,10 +4,10 @@
use crate::mir;
use crate::traits;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::query::caches::DefaultCacheSelector;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_query_system::query::DefaultCacheSelector;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
......
......@@ -61,17 +61,17 @@
#[macro_use]
mod plumbing;
pub(crate) use self::plumbing::CycleError;
use self::plumbing::*;
pub(crate) use rustc_query_system::query::CycleError;
use rustc_query_system::query::*;
mod stats;
pub use self::stats::print_stats;
#[cfg(parallel_compiler)]
mod job;
#[cfg(parallel_compiler)]
pub use self::job::handle_deadlock;
use self::job::QueryJobInfo;
pub use self::job::{QueryInfo, QueryJob, QueryJobId};
pub use rustc_query_system::query::{QueryInfo, QueryJob, QueryJobId};
mod keys;
use self::keys::Key;
......@@ -79,13 +79,9 @@
mod values;
use self::values::Value;
mod caches;
use self::caches::CacheSelector;
mod config;
use self::config::QueryAccessors;
pub use self::config::QueryConfig;
pub(crate) use self::config::QueryDescription;
use rustc_query_system::query::QueryAccessors;
pub use rustc_query_system::query::QueryConfig;
pub(crate) use rustc_query_system::query::QueryDescription;
mod on_disk_cache;
pub use self::on_disk_cache::OnDiskCache;
......
......@@ -994,7 +994,8 @@ fn encode_query_results<'a, 'tcx, Q, E>(
query_result_index: &mut EncodedQueryResultIndex,
) -> Result<(), E::Error>
where
Q: super::config::QueryDescription<'tcx, Value: Encodable>,
Q: super::QueryDescription<TyCtxt<'tcx>>,
Q::Value: Encodable,
E: 'a + TyEncoder,
{
let _timer = tcx
......
此差异已折叠。
use crate::ty::context::TyCtxt;
use crate::ty::query::caches::QueryCache;
use crate::ty::query::plumbing::QueryState;
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_query_system::query::QueryCache;
use rustc_query_system::query::QueryState;
use std::fmt::Debug;
use std::io::Write;
......@@ -160,7 +160,7 @@ impl<T0, T1> IntoSelfProfilingString for (T0, T1)
pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
tcx: TyCtxt<'tcx>,
query_name: &'static str,
query_state: &QueryState<'tcx, C>,
query_state: &QueryState<TyCtxt<'tcx>, C>,
string_cache: &mut QueryKeyStringCache,
) where
C: QueryCache,
......
use crate::ty::query::caches::QueryCache;
use crate::ty::query::config::QueryAccessors;
use crate::ty::query::plumbing::QueryState;
use crate::ty::query::queries;
use crate::ty::TyCtxt;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_query_system::query::QueryCache;
use rustc_query_system::query::QueryState;
use rustc_query_system::query::{QueryAccessors, QueryContext};
use std::any::type_name;
use std::mem;
......@@ -38,7 +38,10 @@ struct QueryStats {
local_def_id_keys: Option<usize>,
}
fn stats<'tcx, C: QueryCache>(name: &'static str, map: &QueryState<'tcx, C>) -> QueryStats {
fn stats<CTX: QueryContext, C: QueryCache>(
name: &'static str,
map: &QueryState<CTX, C>,
) -> QueryStats {
let mut stats = QueryStats {
name,
#[cfg(debug_assertions)]
......@@ -124,7 +127,8 @@ fn query_stats(tcx: TyCtxt<'_>) -> Vec<QueryStats> {
$($(
queries.push(stats::<
<queries::$name<'_> as QueryAccessors<'_>>::Cache,
TyCtxt<'_>,
<queries::$name<'_> as QueryAccessors<TyCtxt<'_>>>::Cache,
>(
stringify!($name),
&tcx.queries.$name,
......
......@@ -7,7 +7,6 @@
use crate::value::Value;
use rustc::bug;
use rustc::dep_graph::DepGraphSafe;
use rustc::mir::mono::CodegenUnit;
use rustc::ty::layout::{
HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx,
......@@ -90,8 +89,6 @@ pub struct CodegenCx<'ll, 'tcx> {
local_gen_sym_counter: Cell<usize>,
}
impl<'ll, 'tcx> DepGraphSafe for CodegenCx<'ll, 'tcx> {}
pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
let reloc_model_arg = match sess.opts.cg.relocation_model {
Some(ref s) => &s[..],
......
......@@ -380,7 +380,7 @@ fn cache_on_disk(
quote! {
#[allow(unused_variables)]
fn describe(
#tcx: TyCtxt<'_>,
#tcx: TyCtxt<'tcx>,
#key: #arg,
) -> Cow<'static, str> {
format!(#desc).into()
......@@ -393,7 +393,7 @@ fn describe(
let desc = desc.unwrap_or(quote! {});
impls.extend(quote! {
impl<'tcx> QueryDescription<'tcx> for queries::#name<'tcx> {
impl<'tcx> QueryDescription<TyCtxt<'tcx>> for queries::#name<'tcx> {
#desc
#cache
}
......@@ -489,7 +489,8 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
::rustc::dep_graph::DepKind::#name => {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
if let Some(key) = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node) {
$tcx.force_query::<crate::ty::query::queries::#name<'_>>(
force_query::<crate::ty::query::queries::#name<'_>, _>(
$tcx,
key,
DUMMY_SP,
*$dep_node
......
......@@ -37,7 +37,7 @@ pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) {
$(fn $name<$lt: $lt, T: IntoArgs>(
$tcx: TyCtxt<$lt>,
def_id_arg: T,
) -> <ty::queries::$name<$lt> as QueryConfig<$lt>>::Value {
) -> <ty::queries::$name<$lt> as QueryConfig<TyCtxt<$lt>>>::Value {
let _prof_timer =
$tcx.prof.generic_activity("metadata_decode_entry");
......
......@@ -11,12 +11,12 @@ doctest = false
[dependencies]
log = { version = "0.4", features = ["release_max_level_info", "std"] }
rustc_ast = { path = "../librustc_ast" }
rustc-rayon-core = "0.3.0"
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_hir = { path = "../librustc_hir" }
rustc_index = { path = "../librustc_index" }
rustc_macros = { path = "../librustc_macros" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
rustc_span = { path = "../librustc_span" }
parking_lot = "0.9"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
......@@ -46,7 +46,6 @@
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable_Generic;
use std::fmt;
use std::hash::Hash;
......@@ -127,7 +126,6 @@ impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T
/// the need to be mapped or unmapped. (This ensures we can serialize
/// them even in the absence of a tcx.)
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
#[derive(HashStable_Generic)]
pub struct WorkProductId {
hash: Fingerprint,
}
......@@ -144,3 +142,10 @@ pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId {
WorkProductId { hash: fingerprint }
}
}
impl<HCX> HashStable<HCX> for WorkProductId {
#[inline]
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
self.hash.hash_stable(hcx, hasher)
}
}
......@@ -20,10 +20,8 @@
use super::debug::EdgeFilter;
use super::prev::PreviousDepGraph;
use super::query::DepGraphQuery;
use super::safe::DepGraphSafe;
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
use super::{DepContext, DepKind, DepNode, WorkProductId};
use crate::{HashStableContext, HashStableContextProvider};
#[derive(Clone)]
pub struct DepGraph<K: DepKind> {
......@@ -191,18 +189,14 @@ pub fn with_ignore<OP, R>(&self, op: OP) -> R
/// `arg` parameter.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
pub fn with_task<H, C, A, R>(
pub fn with_task<Ctxt: DepContext<DepKind = K>, A, R>(
&self,
key: DepNode<K>,
cx: C,
cx: Ctxt,
arg: A,
task: fn(C, A) -> R,
hash_result: impl FnOnce(&mut H, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex)
where
C: DepGraphSafe + HashStableContextProvider<H>,
H: HashStableContext,
{
task: fn(Ctxt, A) -> R,
hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex) {
self.with_task_impl(
key,
cx,
......@@ -223,13 +217,13 @@ pub fn with_task<H, C, A, R>(
)
}
fn with_task_impl<H, C, A, R>(
fn with_task_impl<Ctxt: DepContext<DepKind = K>, A, R>(
&self,
key: DepNode<K>,
cx: C,
cx: Ctxt,
arg: A,
no_tcx: bool,
task: fn(C, A) -> R,
task: fn(Ctxt, A) -> R,
create_task: fn(DepNode<K>) -> Option<TaskDeps<K>>,
finish_task_and_alloc_depnode: fn(
&CurrentDepGraph<K>,
......@@ -237,12 +231,8 @@ fn with_task_impl<H, C, A, R>(
Fingerprint,
Option<TaskDeps<K>>,
) -> DepNodeIndex,
hash_result: impl FnOnce(&mut H, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex)
where
C: DepGraphSafe + HashStableContextProvider<H>,
H: HashStableContext,
{
hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex) {
if let Some(ref data) = self.data {
let task_deps = create_task(key).map(Lock::new);
......@@ -251,7 +241,7 @@ fn with_task_impl<H, C, A, R>(
// anyway so that
// - we make sure that the infrastructure works and
// - we can get an idea of the runtime cost.
let mut hcx = cx.get_stable_hashing_context();
let mut hcx = cx.create_stable_hashing_context();
let result = if no_tcx {
task(cx, arg)
......@@ -268,7 +258,7 @@ fn with_task_impl<H, C, A, R>(
task_deps.map(|lock| lock.into_inner()),
);
let print_status = cfg!(debug_assertions) && hcx.debug_dep_tasks();
let print_status = cfg!(debug_assertions) && cx.debug_dep_tasks();
// Determine the color of the new DepNode.
if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
......@@ -335,18 +325,14 @@ pub fn with_anon_task<OP, R>(&self, dep_kind: K, op: OP) -> (R, DepNodeIndex)
/// Executes something within an "eval-always" task which is a task
/// that runs whenever anything changes.
pub fn with_eval_always_task<H, C, A, R>(
pub fn with_eval_always_task<Ctxt: DepContext<DepKind = K>, A, R>(
&self,
key: DepNode<K>,
cx: C,
cx: Ctxt,
arg: A,
task: fn(C, A) -> R,
hash_result: impl FnOnce(&mut H, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex)
where
C: DepGraphSafe + HashStableContextProvider<H>,
H: HashStableContext,
{
task: fn(Ctxt, A) -> R,
hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex) {
self.with_task_impl(
key,
cx,
......
......@@ -3,7 +3,6 @@
mod graph;
mod prev;
mod query;
mod safe;
mod serialized;
pub use dep_node::{DepNode, DepNodeParams, WorkProductId};
......@@ -11,8 +10,6 @@
pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
pub use prev::PreviousDepGraph;
pub use query::DepGraphQuery;
pub use safe::AssertDepGraphSafe;
pub use safe::DepGraphSafe;
pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};
use rustc_data_structures::profiling::SelfProfilerRef;
......@@ -25,11 +22,13 @@
pub trait DepContext: Copy {
type DepKind: self::DepKind;
type StableHashingContext: crate::HashStableContext;
type StableHashingContext;
/// Create a hashing context for hashing new results.
fn create_stable_hashing_context(&self) -> Self::StableHashingContext;
fn debug_dep_tasks(&self) -> bool;
/// Try to force a dep node to execute and see if it's green.
fn try_force_from_dep_node(&self, dep_node: &DepNode<Self::DepKind>) -> bool;
......@@ -48,12 +47,21 @@ pub trait DepContext: Copy {
/// Register diagnostics for the given node, for use in next session.
fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec<Diagnostic>);
/// Register diagnostics for the given node, for use in next session.
fn store_diagnostics_for_anon_node(
&self,
dep_node_index: DepNodeIndex,
diagnostics: ThinVec<Diagnostic>,
);
/// Access the profiler.
fn profiler(&self) -> &SelfProfilerRef;
}
/// Describe the different families of dependency nodes.
pub trait DepKind: Copy + fmt::Debug + Eq + Ord + Hash {
const NULL: Self;
/// Return whether this kind always require evaluation.
fn is_eval_always(&self) -> bool;
......@@ -72,4 +80,6 @@ fn with_deps<OP, R>(deps: Option<&Lock<TaskDeps<Self>>>, op: OP) -> R
fn read_deps<OP>(op: OP) -> ()
where
OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps<Self>>>) -> ();
fn can_reconstruct_query_key(&self) -> bool;
}
//! The `DepGraphSafe` trait
use rustc_ast::ast::NodeId;
use rustc_hir::def_id::DefId;
use rustc_hir::BodyId;
/// The `DepGraphSafe` trait is used to specify what kinds of values
/// are safe to "leak" into a task. The idea is that this should be
/// only be implemented for things like the tcx as well as various id
/// types, which will create reads in the dep-graph whenever the trait
/// loads anything that might depend on the input program.
pub trait DepGraphSafe {}
/// A `BodyId` on its own doesn't give access to any particular state.
/// You must fetch the state from the various maps or generate
/// on-demand queries, all of which create reads.
impl DepGraphSafe for BodyId {}
/// A `NodeId` on its own doesn't give access to any particular state.
/// You must fetch the state from the various maps or generate
/// on-demand queries, all of which create reads.
impl DepGraphSafe for NodeId {}
/// A `DefId` on its own doesn't give access to any particular state.
/// You must fetch the state from the various maps or generate
/// on-demand queries, all of which create reads.
impl DepGraphSafe for DefId {}
/// Tuples make it easy to build up state.
impl<A, B> DepGraphSafe for (A, B)
where
A: DepGraphSafe,
B: DepGraphSafe,
{
}
/// Shared ref to dep-graph-safe stuff should still be dep-graph-safe.
impl<'a, A> DepGraphSafe for &'a A where A: DepGraphSafe {}
/// Mut ref to dep-graph-safe stuff should still be dep-graph-safe.
impl<'a, A> DepGraphSafe for &'a mut A where A: DepGraphSafe {}
/// No data here! :)
impl DepGraphSafe for () {}
/// A convenient override that lets you pass arbitrary state into a
/// task. Every use should be accompanied by a comment explaining why
/// it makes sense (or how it could be refactored away in the future).
pub struct AssertDepGraphSafe<T>(pub T);
impl<T> DepGraphSafe for AssertDepGraphSafe<T> {}
#![feature(bool_to_option)]
#![feature(const_fn)]
#![feature(const_if_match)]
#![feature(const_panic)]
#![feature(core_intrinsics)]
#![feature(hash_raw_entry)]
#![feature(specialization)]
#![feature(stmt_expr_attributes)]
#![feature(vec_remove_item)]
#[macro_use]
extern crate log;
#[macro_use]
extern crate rustc_data_structures;
pub mod dep_graph;
pub trait HashStableContext {
fn debug_dep_tasks(&self) -> bool;
}
/// Something that can provide a stable hashing context.
pub trait HashStableContextProvider<Ctxt> {
fn get_stable_hashing_context(&self) -> Ctxt;
}
impl<Ctxt, T: HashStableContextProvider<Ctxt>> HashStableContextProvider<Ctxt> for &T {
fn get_stable_hashing_context(&self) -> Ctxt {
(**self).get_stable_hashing_context()
}
}
impl<Ctxt, T: HashStableContextProvider<Ctxt>> HashStableContextProvider<Ctxt> for &mut T {
fn get_stable_hashing_context(&self) -> Ctxt {
(**self).get_stable_hashing_context()
}
}
pub mod query;
For more information about how the query system works, see the [rustc dev guide].
[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
use crate::dep_graph::DepNodeIndex;
use crate::ty::query::plumbing::{QueryLookup, QueryState, QueryStateShard};
use crate::ty::TyCtxt;
use crate::query::plumbing::{QueryLookup, QueryState};
use crate::query::QueryContext;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded::Sharded;
......@@ -8,12 +8,12 @@
use std::hash::Hash;
use std::marker::PhantomData;
pub(crate) trait CacheSelector<K, V> {
pub trait CacheSelector<K: Hash, V> {
type Cache: QueryCache<Key = K, Value = V>;
}
pub(crate) trait QueryCache: Default {
type Key;
pub trait QueryCache: Default {
type Key: Hash;
type Value;
type Sharded: Default;
......@@ -21,25 +21,21 @@ pub(crate) trait QueryCache: Default {
/// It returns the shard index and a lock guard to the shard,
/// which will be used if the query is not in the cache and we need
/// to compute it.
fn lookup<'tcx, R, GetCache, OnHit, OnMiss>(
fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
&self,
state: &'tcx QueryState<'tcx, Self>,
get_cache: GetCache,
state: &QueryState<CTX, Self>,
key: Self::Key,
// `on_hit` can be called while holding a lock to the query state shard.
on_hit: OnHit,
on_miss: OnMiss,
) -> R
where
GetCache: for<'a> Fn(
&'a mut QueryStateShard<'tcx, Self::Key, Self::Sharded>,
) -> &'a mut Self::Sharded,
OnHit: FnOnce(&Self::Value, DepNodeIndex) -> R,
OnMiss: FnOnce(Self::Key, QueryLookup<'tcx, Self::Key, Self::Sharded>) -> R;
OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;
fn complete(
fn complete<CTX: QueryContext>(
&self,
tcx: TyCtxt<'tcx>,
tcx: CTX,
lock_sharded_storage: &mut Self::Sharded,
key: Self::Key,
value: Self::Value,
......@@ -76,32 +72,29 @@ impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
type Sharded = FxHashMap<K, (V, DepNodeIndex)>;
#[inline(always)]
fn lookup<'tcx, R, GetCache, OnHit, OnMiss>(
fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
&self,
state: &'tcx QueryState<'tcx, Self>,
get_cache: GetCache,
state: &QueryState<CTX, Self>,
key: K,
on_hit: OnHit,
on_miss: OnMiss,
) -> R
where
GetCache:
for<'a> Fn(&'a mut QueryStateShard<'tcx, K, Self::Sharded>) -> &'a mut Self::Sharded,
OnHit: FnOnce(&V, DepNodeIndex) -> R,
OnMiss: FnOnce(K, QueryLookup<'tcx, K, Self::Sharded>) -> R,
OnMiss: FnOnce(K, QueryLookup<'_, CTX, K, Self::Sharded>) -> R,
{
let mut lookup = state.get_lookup(&key);
let lock = &mut *lookup.lock;
let result = get_cache(lock).raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);
let result = lock.cache.raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);
if let Some((_, value)) = result { on_hit(&value.0, value.1) } else { on_miss(key, lookup) }
}
#[inline]
fn complete(
fn complete<CTX: QueryContext>(
&self,
_: TyCtxt<'tcx>,
_: CTX,
lock_sharded_storage: &mut Self::Sharded,
key: K,
value: V,
......
//! Query configuration and description traits.
use crate::dep_graph::DepNode;
use crate::dep_graph::SerializedDepNodeIndex;
use crate::dep_graph::{DepKind, DepNode};
use crate::ty::query::caches::QueryCache;
use crate::ty::query::plumbing::CycleError;
use crate::ty::query::QueryState;
use crate::ty::TyCtxt;
use crate::query::caches::QueryCache;
use crate::query::plumbing::CycleError;
use crate::query::{QueryContext, QueryState};
use rustc_data_structures::profiling::ProfileCategory;
use rustc_hir::def_id::DefId;
use rustc_span::def_id::DefId;
use crate::ich::StableHashingContext;
use rustc_data_structures::fingerprint::Fingerprint;
use std::borrow::Cow;
use std::fmt::Debug;
use std::hash::Hash;
// Query configuration and description traits.
// FIXME(eddyb) false positive, the lifetime parameter is used for `Key`/`Value`.
#[allow(unused_lifetimes)]
pub trait QueryConfig<'tcx> {
// The parameter `CTX` is required in librustc: implementations may need to access the `'tcx`
// lifetime in `CTX = TyCtxt<'tcx>`.
pub trait QueryConfig<CTX> {
const NAME: &'static str;
const CATEGORY: ProfileCategory;
......@@ -25,43 +23,48 @@ pub trait QueryConfig<'tcx> {
type Value: Clone;
}
pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
pub trait QueryAccessors<CTX: QueryContext>: QueryConfig<CTX> {
const ANON: bool;
const EVAL_ALWAYS: bool;
const DEP_KIND: DepKind;
const DEP_KIND: CTX::DepKind;
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
// Don't use this method to access query results, instead use the methods on TyCtxt
fn query_state<'a>(tcx: TyCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Cache>;
fn query_state<'a>(tcx: CTX) -> &'a QueryState<CTX, Self::Cache>;
fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;
fn to_dep_node(tcx: CTX, key: &Self::Key) -> DepNode<CTX::DepKind>;
// Don't use this method to compute query results, instead use the methods on TyCtxt
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;
fn compute(tcx: CTX, key: Self::Key) -> Self::Value;
fn hash_result(hcx: &mut StableHashingContext<'_>, result: &Self::Value)
-> Option<Fingerprint>;
fn hash_result(
hcx: &mut CTX::StableHashingContext,
result: &Self::Value,
) -> Option<Fingerprint>;
fn handle_cycle_error(tcx: TyCtxt<'tcx>, error: CycleError<'tcx>) -> Self::Value;
fn handle_cycle_error(tcx: CTX, error: CycleError<CTX::Query>) -> Self::Value;
}
pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
fn describe(tcx: TyCtxt<'_>, key: Self::Key) -> Cow<'static, str>;
pub trait QueryDescription<CTX: QueryContext>: QueryAccessors<CTX> {
fn describe(tcx: CTX, key: Self::Key) -> Cow<'static, str>;
#[inline]
fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
fn cache_on_disk(_: CTX, _: Self::Key, _: Option<&Self::Value>) -> bool {
false
}
fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option<Self::Value> {
bug!("QueryDescription::load_from_disk() called for an unsupported query.")
fn try_load_from_disk(_: CTX, _: SerializedDepNodeIndex) -> Option<Self::Value> {
panic!("QueryDescription::load_from_disk() called for an unsupported query.")
}
}
impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M {
default fn describe(tcx: TyCtxt<'_>, def_id: DefId) -> Cow<'static, str> {
if !tcx.sess.verbose() {
impl<CTX: QueryContext, M> QueryDescription<CTX> for M
where
M: QueryAccessors<CTX, Key = DefId>,
{
default fn describe(tcx: CTX, def_id: DefId) -> Cow<'static, str> {
if !tcx.verbose() {
format!("processing `{}`", tcx.def_path_str(def_id)).into()
} else {
let name = ::std::any::type_name::<M>();
......@@ -69,14 +72,11 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M {
}
}
default fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
default fn cache_on_disk(_: CTX, _: Self::Key, _: Option<&Self::Value>) -> bool {
false
}
default fn try_load_from_disk(
_: TyCtxt<'tcx>,
_: SerializedDepNodeIndex,
) -> Option<Self::Value> {
bug!("QueryDescription::load_from_disk() called for an unsupported query.")
default fn try_load_from_disk(_: CTX, _: SerializedDepNodeIndex) -> Option<Self::Value> {
panic!("QueryDescription::load_from_disk() called for an unsupported query.")
}
}
此差异已折叠。
mod plumbing;
pub use self::plumbing::*;
mod job;
#[cfg(parallel_compiler)]
pub use self::job::deadlock;
pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
mod caches;
pub use self::caches::{CacheSelector, DefaultCacheSelector, QueryCache};
mod config;
pub use self::config::{QueryAccessors, QueryConfig, QueryDescription};
use crate::dep_graph::{DepContext, DepGraph};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::HashStable;
use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::Diagnostic;
use rustc_span::def_id::DefId;
pub trait QueryContext: DepContext {
type Query: Clone + HashStable<Self::StableHashingContext>;
fn incremental_verify_ich(&self) -> bool;
fn verbose(&self) -> bool;
/// Get string representation from DefPath.
fn def_path_str(&self, def_id: DefId) -> String;
/// Access the DepGraph.
fn dep_graph(&self) -> &DepGraph<Self::DepKind>;
/// Get the query information from the TLS context.
fn current_query_job(&self) -> Option<QueryJobId<Self::DepKind>>;
fn try_collect_active_jobs(
&self,
) -> Option<FxHashMap<QueryJobId<Self::DepKind>, QueryJobInfo<Self>>>;
/// Executes a job by changing the `ImplicitCtxt` to point to the
/// new query job while it executes. It returns the diagnostics
/// captured during execution and the actual result.
fn start_query<R>(
&self,
token: QueryJobId<Self::DepKind>,
diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
compute: impl FnOnce(Self) -> R,
) -> R;
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册