Auto merge of #101307 - jyn514:simplify-storage, r=cjgillot

Simplify caching and storage for queries

I highly recommend reviewing commit-by-commit; each individual commit is quite small but it can be hard to see looking at the overall diff that the behavior is the same. Each commit depends on the previous.

r? `@cjgillot`
This commit is contained in:
bors 2022-09-14 02:39:51 +00:00
commit a5b58addae
7 changed files with 107 additions and 153 deletions

View File

@ -86,14 +86,11 @@ struct QueryModifiers {
desc: (Option<Ident>, Punctuated<Expr, Token![,]>),
/// Use this type for the in-memory cache.
storage: Option<Type>,
arena_cache: Option<Ident>,
/// Cache the query to disk if the `Block` returns true.
cache: Option<(Option<Pat>, Block)>,
/// Custom code to load the query from disk.
load_cached: Option<(Ident, Ident, Block)>,
/// A cycle error for this query aborting the compilation with a fatal error.
fatal_cycle: Option<Ident>,
@ -120,8 +117,7 @@ struct QueryModifiers {
}
fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
let mut load_cached = None;
let mut storage = None;
let mut arena_cache = None;
let mut cache = None;
let mut desc = None;
let mut fatal_cycle = None;
@ -173,21 +169,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
};
let block = input.parse()?;
try_insert!(cache = (args, block));
} else if modifier == "load_cached" {
// Parse a load_cached modifier like:
// `load_cached(tcx, id) { tcx.on_disk_cache.try_load_query_result(tcx, id) }`
let args;
parenthesized!(args in input);
let tcx = args.parse()?;
args.parse::<Token![,]>()?;
let id = args.parse()?;
let block = input.parse()?;
try_insert!(load_cached = (tcx, id, block));
} else if modifier == "storage" {
let args;
parenthesized!(args in input);
let ty = args.parse()?;
try_insert!(storage = ty);
} else if modifier == "arena_cache" {
try_insert!(arena_cache = modifier);
} else if modifier == "fatal_cycle" {
try_insert!(fatal_cycle = modifier);
} else if modifier == "cycle_delay_bug" {
@ -212,8 +195,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
return Err(input.error("no description provided"));
};
Ok(QueryModifiers {
load_cached,
storage,
arena_cache,
cache,
desc,
fatal_cycle,
@ -262,20 +244,6 @@ fn add_query_description_impl(query: &Query, impls: &mut proc_macro2::TokenStrea
// Find out if we should cache the query on disk
let cache = if let Some((args, expr)) = modifiers.cache.as_ref() {
let try_load_from_disk = if let Some((tcx, id, block)) = modifiers.load_cached.as_ref() {
// Use custom code to load the query from disk
quote! {
const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<'tcx>, SerializedDepNodeIndex) -> Option<Self::Value>>
= Some(|#tcx, #id| { #block });
}
} else {
// Use the default code to load the query from disk
quote! {
const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<'tcx>, SerializedDepNodeIndex) -> Option<Self::Value>>
= Some(|tcx, id| tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id));
}
};
let tcx = args.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ });
// expr is a `Block`, meaning that `{ #expr }` gets expanded
// to `{ { stmts... } }`, which triggers the `unused_braces` lint.
@ -285,20 +253,13 @@ fn add_query_description_impl(query: &Query, impls: &mut proc_macro2::TokenStrea
fn cache_on_disk(#tcx: TyCtxt<'tcx>, #key: &Self::Key) -> bool {
#expr
}
#try_load_from_disk
}
} else {
if modifiers.load_cached.is_some() {
panic!("load_cached modifier on query `{}` without a cache modifier", name);
}
quote! {
#[inline]
fn cache_on_disk(_: TyCtxt<'tcx>, _: &Self::Key) -> bool {
false
}
const TRY_LOAD_FROM_DISK: Option<fn(QueryCtxt<'tcx>, SerializedDepNodeIndex) -> Option<Self::Value>> = None;
}
};
@ -347,42 +308,28 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
let mut attributes = Vec::new();
// Pass on the fatal_cycle modifier
if let Some(fatal_cycle) = &modifiers.fatal_cycle {
attributes.push(quote! { (#fatal_cycle) });
};
// Pass on the storage modifier
if let Some(ref ty) = modifiers.storage {
let span = ty.span();
attributes.push(quote_spanned! {span=> (storage #ty) });
};
// Pass on the cycle_delay_bug modifier
if let Some(cycle_delay_bug) = &modifiers.cycle_delay_bug {
attributes.push(quote! { (#cycle_delay_bug) });
};
// Pass on the no_hash modifier
if let Some(no_hash) = &modifiers.no_hash {
attributes.push(quote! { (#no_hash) });
};
// Pass on the anon modifier
if let Some(anon) = &modifiers.anon {
attributes.push(quote! { (#anon) });
};
// Pass on the eval_always modifier
if let Some(eval_always) = &modifiers.eval_always {
attributes.push(quote! { (#eval_always) });
};
// Pass on the depth_limit modifier
if let Some(depth_limit) = &modifiers.depth_limit {
attributes.push(quote! { (#depth_limit) });
};
// Pass on the separate_provide_extern modifier
if let Some(separate_provide_extern) = &modifiers.separate_provide_extern {
attributes.push(quote! { (#separate_provide_extern) });
macro_rules! passthrough {
( $( $modifier:ident ),+ $(,)? ) => {
$( if let Some($modifier) = &modifiers.$modifier {
attributes.push(quote! { (#$modifier) });
}; )+
}
}
// Pass on the remap_env_constness modifier
if let Some(remap_env_constness) = &modifiers.remap_env_constness {
attributes.push(quote! { (#remap_env_constness) });
passthrough!(
fatal_cycle,
arena_cache,
cycle_delay_bug,
no_hash,
anon,
eval_always,
depth_limit,
separate_provide_extern,
remap_env_constness,
);
if modifiers.cache.is_some() {
attributes.push(quote! { (cache) });
}
// This uses the span of the query definition for the commas,

View File

@ -47,14 +47,14 @@ rustc_queries! {
/// To avoid this fate, do not call `tcx.hir().krate()`; instead,
/// prefer wrappers like `tcx.visit_all_items_in_krate()`.
query hir_crate(key: ()) -> Crate<'tcx> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "get the crate HIR" }
}
/// All items in the crate.
query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "get HIR crate items" }
}
@ -64,7 +64,7 @@ rustc_queries! {
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
/// Avoid calling this query directly.
query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
@ -196,7 +196,7 @@ rustc_queries! {
/// associated generics.
query generics_of(key: DefId) -> ty::Generics {
desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) }
storage(ArenaCacheSelector<'tcx>)
arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
@ -268,13 +268,13 @@ rustc_queries! {
}
query native_libraries(_: CrateNum) -> Vec<NativeLib> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "looking up the native libraries of a linked crate" }
separate_provide_extern
}
query lint_levels(_: ()) -> LintLevelMap {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "computing the lint levels for items in this crate" }
}
@ -307,7 +307,7 @@ rustc_queries! {
/// Create a THIR tree for debugging.
query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> String {
no_hash
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) }
}
@ -315,7 +315,7 @@ rustc_queries! {
/// them. This includes all the body owners, but also things like struct
/// constructors.
query mir_keys(_: ()) -> rustc_data_structures::fx::FxIndexSet<LocalDefId> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "getting a list of all mir_keys" }
}
@ -422,7 +422,7 @@ rustc_queries! {
query symbols_for_closure_captures(
key: (LocalDefId, LocalDefId)
) -> Vec<rustc_span::Symbol> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc {
|tcx| "symbols for captures of closure `{}` in `{}`",
tcx.def_path_str(key.1.to_def_id()),
@ -442,7 +442,7 @@ rustc_queries! {
/// MIR pass (assuming the -Cinstrument-coverage option is enabled).
query coverageinfo(key: ty::InstanceDef<'tcx>) -> mir::CoverageInfo {
desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) }
storage(ArenaCacheSelector<'tcx>)
arena_cache
}
/// Returns the `CodeRegions` for a function that has instrumented coverage, in case the
@ -452,7 +452,7 @@ rustc_queries! {
|tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`",
tcx.def_path_str(key)
}
storage(ArenaCacheSelector<'tcx>)
arena_cache
cache_on_disk_if { key.is_local() }
}
@ -490,7 +490,7 @@ rustc_queries! {
}
query wasm_import_module_map(_: CrateNum) -> FxHashMap<DefId, String> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "wasm import module map" }
}
@ -566,7 +566,7 @@ rustc_queries! {
query trait_def(key: DefId) -> ty::TraitDef {
desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) }
storage(ArenaCacheSelector<'tcx>)
arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
@ -644,7 +644,7 @@ rustc_queries! {
/// Gets a map with the variance of every item; use `item_variance` instead.
query crate_variances(_: ()) -> ty::CrateVariancesMap<'tcx> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "computing the variances for items in this crate" }
}
@ -657,7 +657,7 @@ rustc_queries! {
/// Maps from thee `DefId` of a type to its (inferred) outlives.
query inferred_outlives_crate(_: ()) -> ty::CratePredicatesMap<'tcx> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "computing the inferred outlives predicates for items in this crate" }
}
@ -671,14 +671,14 @@ rustc_queries! {
/// Maps from a trait item to the trait item "descriptor".
query associated_item(key: DefId) -> ty::AssocItem {
desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
storage(ArenaCacheSelector<'tcx>)
arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
/// Collects the associated items defined on a trait or impl.
query associated_items(key: DefId) -> ty::AssocItems<'tcx> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
}
@ -704,7 +704,7 @@ rustc_queries! {
/// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be
///`{ trait_f: impl_f, trait_g: impl_g }`
query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "comparing impl items against trait for {}", tcx.def_path_str(impl_id) }
}
@ -837,7 +837,7 @@ rustc_queries! {
FxHashSet<LocalDefId>,
FxHashMap<LocalDefId, Vec<(DefId, DefId)>>
) {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "find live symbols in crate" }
}
@ -883,13 +883,6 @@ rustc_queries! {
query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
load_cached(tcx, id) {
let typeck_results: Option<ty::TypeckResults<'tcx>> = tcx
.on_disk_cache().as_ref()
.and_then(|c| c.try_load_query_result(*tcx, id));
typeck_results.map(|x| &*tcx.arena.alloc(x))
}
}
query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet<LocalDefId> {
@ -921,7 +914,7 @@ rustc_queries! {
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
query crate_inherent_impls(k: ()) -> CrateInherentImpls {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "all inherent impls defined in crate" }
}
@ -1054,7 +1047,7 @@ rustc_queries! {
}
query reachable_set(_: ()) -> FxHashSet<LocalDefId> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "reachability" }
}
@ -1066,7 +1059,7 @@ rustc_queries! {
/// Generates a MIR body for the shim.
query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
}
@ -1140,7 +1133,7 @@ rustc_queries! {
query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs {
desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) }
storage(ArenaCacheSelector<'tcx>)
arena_cache
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
}
@ -1157,7 +1150,7 @@ rustc_queries! {
/// Gets the rendered value of the specified constant or associated constant.
/// Used by rustdoc.
query rendered_const(def_id: DefId) -> String {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
@ -1216,12 +1209,12 @@ rustc_queries! {
/// Given a trait `trait_id`, return all known `impl` blocks.
query trait_impls_of(trait_id: DefId) -> ty::trait_def::TraitImpls {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "trait impls of `{}`", tcx.def_path_str(trait_id) }
}
query specialization_graph_of(trait_id: DefId) -> specialization_graph::Graph {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
cache_on_disk_if { true }
}
@ -1348,7 +1341,7 @@ rustc_queries! {
}
query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "get the linkage format of all dependencies" }
}
@ -1441,7 +1434,7 @@ rustc_queries! {
// like the compiler-generated `main` function and so on.
query reachable_non_generics(_: CrateNum)
-> DefIdMap<SymbolExportInfo> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "looking up the exported symbols of a crate" }
separate_provide_extern
}
@ -1464,7 +1457,7 @@ rustc_queries! {
/// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
/// better, `Instance::upstream_monomorphization()`.
query upstream_monomorphizations(_: ()) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "collecting available upstream monomorphizations" }
}
@ -1478,7 +1471,7 @@ rustc_queries! {
query upstream_monomorphizations_for(def_id: DefId)
-> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>>
{
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx|
"collecting available upstream monomorphizations for `{}`",
tcx.def_path_str(def_id),
@ -1506,7 +1499,7 @@ rustc_queries! {
}
query foreign_modules(_: CrateNum) -> FxHashMap<DefId, ForeignModule> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "looking up the foreign modules of a linked crate" }
separate_provide_extern
}
@ -1532,13 +1525,13 @@ rustc_queries! {
separate_provide_extern
}
query extra_filename(_: CrateNum) -> String {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "looking up the extra filename for a crate" }
separate_provide_extern
}
query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "looking up the paths for extern crates" }
separate_provide_extern
@ -1580,14 +1573,14 @@ rustc_queries! {
/// the same lifetimes and is responsible for diagnostics.
/// See `rustc_resolve::late::lifetimes for details.
query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "resolving lifetimes for a trait definition" }
}
/// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params.
/// See `rustc_resolve::late::lifetimes for details.
query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "resolving lifetimes" }
}
query named_region_map(_: LocalDefId) ->
@ -1657,7 +1650,7 @@ rustc_queries! {
}
query lib_features(_: ()) -> LibFeatures {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "calculating the lib features map" }
}
query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
@ -1665,7 +1658,7 @@ rustc_queries! {
separate_provide_extern
}
query stability_implications(_: CrateNum) -> FxHashMap<Symbol, Symbol> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "calculating the implications between `#[unstable]` features defined in a crate" }
separate_provide_extern
}
@ -1676,14 +1669,14 @@ rustc_queries! {
}
/// Returns the lang items defined in another crate by loading it from metadata.
query get_lang_items(_: ()) -> LanguageItems {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "calculating the lang items map" }
}
/// Returns all diagnostic items defined in all crates.
query all_diagnostic_items(_: ()) -> rustc_hir::diagnostic_items::DiagnosticItems {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "calculating the diagnostic items map" }
}
@ -1696,7 +1689,7 @@ rustc_queries! {
/// Returns the diagnostic items defined in a crate.
query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "calculating the diagnostic items map in a crate" }
separate_provide_extern
}
@ -1706,11 +1699,11 @@ rustc_queries! {
separate_provide_extern
}
query visible_parent_map(_: ()) -> DefIdMap<DefId> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "calculating the visible parent map" }
}
query trimmed_def_paths(_: ()) -> FxHashMap<DefId, Symbol> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "calculating trimmed def paths" }
}
query missing_extern_crate_item(_: CrateNum) -> bool {
@ -1719,14 +1712,14 @@ rustc_queries! {
separate_provide_extern
}
query used_crate_source(_: CrateNum) -> Lrc<CrateSource> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "looking at the source for a crate" }
separate_provide_extern
}
/// Returns the debugger visualizers defined for this crate.
query debugger_visualizers(_: CrateNum) -> Vec<rustc_span::DebuggerVisualizerFile> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { "looking up the debugger visualizers for this crate" }
separate_provide_extern
}
@ -1760,7 +1753,7 @@ rustc_queries! {
}
query stability_index(_: ()) -> stability::Index {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "calculating the stability index for the local crate" }
}
@ -2001,7 +1994,7 @@ rustc_queries! {
}
query supported_target_features(_: CrateNum) -> FxHashMap<String, Option<Symbol>> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "looking up supported target features" }
}
@ -2071,7 +2064,7 @@ rustc_queries! {
/// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
/// because the `ty::Ty`-based wfcheck is always run.
query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
no_hash
desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }
@ -2081,13 +2074,13 @@ rustc_queries! {
/// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
query global_backend_features(_: ()) -> Vec<String> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
eval_always
desc { "computing the backend features for CLI flags" }
}
query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> {
storage(ArenaCacheSelector<'tcx>)
arena_cache
desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
separate_provide_extern
}

View File

@ -121,8 +121,8 @@ macro_rules! query_storage {
([][$K:ty, $V:ty]) => {
<DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
};
([(storage $ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
<$ty as CacheSelector<$K, $V>>::Cache
([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
<ArenaCacheSelector<'tcx> as CacheSelector<$K, $V>>::Cache
};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
query_storage!([$($modifiers)*][$($args)*])

View File

@ -17,7 +17,7 @@ extern crate rustc_middle;
use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex};
use rustc_middle::dep_graph::{self, DepKindStruct};
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
use rustc_middle::ty::{self, TyCtxt};

View File

@ -3,6 +3,7 @@
//! manage the caches, and so forth.
use crate::keys::Key;
use crate::on_disk_cache::CacheDecoder;
use crate::{on_disk_cache, Queries};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{AtomicU64, Lock};
@ -19,6 +20,7 @@ use rustc_query_system::query::{
QuerySideEffects, QueryStackFrame,
};
use rustc_query_system::Value;
use rustc_serialize::Decodable;
use std::any::Any;
use std::num::NonZeroU64;
use thin_vec::ThinVec;
@ -253,6 +255,18 @@ macro_rules! get_provider {
};
}
macro_rules! should_ever_cache_on_disk {
([]) => {{
None
}};
([(cache) $($rest:tt)*]) => {{
Some($crate::plumbing::try_load_from_disk::<Self::Value>)
}};
([$other:tt $($modifiers:tt)*]) => {
should_ever_cache_on_disk!([$($modifiers)*])
};
}
pub(crate) fn create_query_frame<
'tcx,
K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
@ -313,6 +327,16 @@ where
}
}
pub(crate) fn try_load_from_disk<'tcx, V>(
tcx: QueryCtxt<'tcx>,
id: SerializedDepNodeIndex,
) -> Option<V>
where
V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
}
fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
where
Q: QueryDescription<QueryCtxt<'tcx>>,
@ -418,8 +442,7 @@ macro_rules! define_queries {
hash_result: hash_result!([$($modifiers)*]),
handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
compute,
cache_on_disk,
try_load_from_disk: Self::TRY_LOAD_FROM_DISK,
try_load_from_disk: if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None },
}
}

View File

@ -25,11 +25,11 @@ pub struct QueryVTable<CTX: QueryContext, K, V> {
pub dep_kind: CTX::DepKind,
pub eval_always: bool,
pub depth_limit: bool,
pub cache_on_disk: bool,
pub compute: fn(CTX::DepContext, K) -> V,
pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
pub handle_cycle_error: HandleCycleError,
// NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query
pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>,
}
@ -44,18 +44,9 @@ impl<CTX: QueryContext, K, V> QueryVTable<CTX, K, V> {
pub(crate) fn compute(&self, tcx: CTX::DepContext, key: K) -> V {
(self.compute)(tcx, key)
}
pub(crate) fn try_load_from_disk(&self, tcx: CTX, index: SerializedDepNodeIndex) -> Option<V> {
self.try_load_from_disk
.expect("QueryDescription::load_from_disk() called for an unsupported query.")(
tcx, index,
)
}
}
pub trait QueryDescription<CTX: QueryContext>: QueryConfig {
const TRY_LOAD_FROM_DISK: Option<fn(CTX, SerializedDepNodeIndex) -> Option<Self::Value>>;
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
fn describe(tcx: CTX, key: Self::Key) -> String;

View File

@ -488,14 +488,14 @@ where
// First we try to load the result from the on-disk cache.
// Some things are never cached on disk.
if query.cache_on_disk {
if let Some(try_load_from_disk) = query.try_load_from_disk {
let prof_timer = tcx.dep_context().profiler().incr_cache_loading();
// The call to `with_query_deserialization` enforces that no new `DepNodes`
// are created during deserialization. See the docs of that method for more
// details.
let result = dep_graph
.with_query_deserialization(|| query.try_load_from_disk(tcx, prev_dep_node_index));
let result =
dep_graph.with_query_deserialization(|| try_load_from_disk(tcx, prev_dep_node_index));
prof_timer.finish_with_query_invocation_id(dep_node_index.into());