Move OnDiskCache to rustc_query_impl.

This commit is contained in:
Camille GILLOT 2021-06-28 21:12:01 +02:00
parent 68511b574f
commit 81241cbf3a
14 changed files with 226 additions and 197 deletions

View File

@ -4242,12 +4242,16 @@ version = "0.0.0"
dependencies = [
"measureme",
"rustc-rayon-core",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
"tracing",
]

View File

@ -2,7 +2,7 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::query::OnDiskCache;
use rustc_middle::ty::OnDiskCache;
use rustc_serialize::opaque::Decoder;
use rustc_serialize::Decodable;
use rustc_session::Session;
@ -198,7 +198,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
/// If we are not in incremental compilation mode, returns `None`.
/// Otherwise, tries to load the query result cache from disk,
/// creating an empty cache if it could not be loaded.
pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option<OnDiskCache<'a>> {
pub fn load_query_result_cache<'a, C: OnDiskCache<'a>>(sess: &'a Session) -> Option<C> {
if sess.opts.incremental.is_none() {
return None;
}
@ -210,9 +210,7 @@ pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option<OnDiskCache<'a>>
&query_cache_path(sess),
sess.is_nightly_build(),
) {
LoadResult::Ok { data: (bytes, start_pos) } => {
Some(OnDiskCache::new(sess, bytes, start_pos))
}
_ => Some(OnDiskCache::new_empty(sess.source_map())),
LoadResult::Ok { data: (bytes, start_pos) } => Some(C::new(sess, bytes, start_pos)),
_ => Some(C::new_empty(sess.source_map())),
}
}

View File

@ -12,6 +12,7 @@ use rustc_errors::{ErrorReported, Handler};
use rustc_lint::LintStore;
use rustc_middle::ty;
use rustc_parse::new_parser_from_source_str;
use rustc_query_impl::QueryCtxt;
use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames};
use rustc_session::early_error;
use rustc_session::lint;
@ -233,7 +234,7 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
// state if it was responsible for triggering the panic.
let i = ty::tls::with_context_opt(|icx| {
if let Some(icx) = icx {
icx.tcx.queries.try_print_query_stack(icx.tcx, icx.query, handler, num_frames)
QueryCtxt::from_tcx(icx.tcx).try_print_query_stack(icx.query, handler, num_frames)
} else {
0
}

View File

@ -26,7 +26,7 @@ use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
use rustc_passes::{self, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_query_impl::Queries as TcxQueries;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_serialize::json;
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode};
@ -819,7 +819,9 @@ pub fn create_global_ctxt<'tcx>(
callback(sess, &mut local_providers, &mut extern_providers);
}
let queries = queries.get_or_init(|| TcxQueries::new(local_providers, extern_providers));
let queries = queries.get_or_init(|| {
TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
});
let gcx = sess.time("setup_global_ctxt", || {
global_ctxt.get_or_init(move || {
@ -830,7 +832,7 @@ pub fn create_global_ctxt<'tcx>(
resolver_outputs,
krate,
dep_graph,
query_result_on_disk_cache,
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
queries.as_dyn(),
&crate_name,
outputs,

View File

@ -367,7 +367,7 @@ fn add_query_description_impl(
tcx: QueryCtxt<'tcx>,
id: SerializedDepNodeIndex
) -> Option<Self::Value> {
tcx.on_disk_cache.as_ref()?.try_load_query_result(*tcx, id)
tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
}
}
};

View File

@ -131,7 +131,10 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
impl CStore {
pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore {
tcx.cstore_as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
tcx.cstore_untracked()
.as_any()
.downcast_ref::<CStore>()
.expect("`tcx.cstore` is not a `CStore`")
}
fn alloc_new_crate_num(&mut self) -> CrateNum {

View File

@ -724,7 +724,7 @@ rustc_queries! {
cache_on_disk_if { true }
load_cached(tcx, id) {
let typeck_results: Option<ty::TypeckResults<'tcx>> = tcx
.on_disk_cache.as_ref()
.on_disk_cache().as_ref()
.and_then(|c| c.try_load_query_result(*tcx, id));
typeck_results.map(|x| &*tcx.arena.alloc(x))

View File

@ -1,7 +1,7 @@
//! Type context book-keeping.
use crate::arena::Arena;
use crate::dep_graph::DepGraph;
use crate::dep_graph::{DepGraph, DepNode};
use crate::hir::place::Place as HirPlace;
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
@ -14,7 +14,7 @@ use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::thir::Thir;
use crate::traits;
use crate::ty::query::{self, OnDiskCache, TyCtxtAt};
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
use crate::ty::TyKind::*;
use crate::ty::{
@ -52,8 +52,8 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
use rustc_session::lint::{Level, Lint};
use rustc_session::Limit;
use rustc_session::Session;
use rustc_span::def_id::StableCrateId;
use rustc_span::source_map::MultiSpan;
use rustc_span::def_id::{DefPathHash, StableCrateId};
use rustc_span::source_map::{MultiSpan, SourceMap};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
@ -71,6 +71,40 @@ use std::mem;
use std::ops::{Bound, Deref};
use std::sync::Arc;
pub trait OnDiskCache<'tcx> {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
fn new(sess: &'tcx Session, data: Vec<u8>, start_pos: usize) -> Self
where
Self: Sized;
fn new_empty(source_map: &'tcx SourceMap) -> Self
where
Self: Sized;
/// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
/// session, if it still exists. This is used during incremental compilation to
/// turn a deserialized `DefPathHash` into its current `DefId`.
fn def_path_hash_to_def_id(
&self,
tcx: TyCtxt<'tcx>,
def_path_hash: DefPathHash,
) -> Option<DefId>;
/// If the given `dep_node`'s hash still exists in the current compilation,
/// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
///
/// Normally, `store_foreign_def_id_hash` can be called directly by
/// the dependency graph when we construct a `DepNode`. However,
/// when we re-use a deserialized `DepNode` from the previous compilation
/// session, we only have the `DefPathHash` available. This method is used
/// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
/// out for usage in the next compilation session.
fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode);
fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash);
fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult;
}
/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
@ -993,7 +1027,7 @@ pub struct GlobalCtxt<'tcx> {
/// Do not access this directly. It is only meant to be used by
/// `DepGraph::try_mark_green()` and the query infrastructure.
/// This is `None` if we are not incremental compilation mode
pub on_disk_cache: Option<OnDiskCache<'tcx>>,
pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
pub query_caches: query::QueryCaches<'tcx>,
@ -1141,7 +1175,7 @@ impl<'tcx> TyCtxt<'tcx> {
resolutions: ty::ResolverOutputs,
krate: &'tcx hir::Crate<'tcx>,
dep_graph: DepGraph,
on_disk_cache: Option<query::OnDiskCache<'tcx>>,
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
queries: &'tcx dyn query::QueryEngine<'tcx>,
crate_name: &str,
output_filenames: OutputFilenames,
@ -1308,10 +1342,16 @@ impl<'tcx> TyCtxt<'tcx> {
self.untracked_resolutions.cstore.encode_metadata(self)
}
// Note that this is *untracked* and should only be used within the query
// system if the result is otherwise tracked through queries
pub fn cstore_as_any(self) -> &'tcx dyn Any {
self.untracked_resolutions.cstore.as_any()
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
pub fn cstore_untracked(self) -> &'tcx ty::CrateStoreDyn {
&*self.untracked_resolutions.cstore
}
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
pub fn definitions_untracked(self) -> &'tcx hir::definitions::Definitions {
&self.untracked_resolutions.definitions
}
#[inline(always)]

View File

@ -59,7 +59,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Uneval
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
Lift, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
};
pub use self::instance::{Instance, InstanceDef};
pub use self::list::List;

View File

@ -38,14 +38,13 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{ErrorReported, Handler};
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_serialize::opaque;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind;
use rustc_session::Limits;
@ -63,9 +62,6 @@ use std::sync::Arc;
pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;
pub mod on_disk_cache;
pub use self::on_disk_cache::OnDiskCache;
#[derive(Copy, Clone)]
pub struct TyCtxtAt<'tcx> {
pub tcx: TyCtxt<'tcx>,
@ -235,28 +231,13 @@ macro_rules! define_callbacks {
}
pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
#[cfg(parallel_compiler)]
unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry);
fn encode_query_results(
&'tcx self,
tcx: TyCtxt<'tcx>,
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
) -> opaque::FileEncodeResult;
fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>);
fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
fn try_print_query_stack(
&'tcx self,
tcx: TyCtxt<'tcx>,
query: Option<QueryJobId<dep_graph::DepKind>>,
handler: &Handler,
num_frames: Option<usize>,
) -> usize;
$($(#[$attr])*
fn $name(
&'tcx self,

View File

@ -11,10 +11,14 @@ doctest = false
measureme = "9.0.0"
rustc-rayon-core = "0.3.1"
tracing = "0.1"
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_span = { path = "../rustc_span" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }

View File

@ -1,12 +1,16 @@
//! Support for serializing the dep-graph and reloading it.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#[macro_use]
extern crate rustc_macros;
#[macro_use]
extern crate rustc_middle;
#[macro_use]
@ -14,13 +18,12 @@ extern crate tracing;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::{DiagnosticBuilder, Handler};
use rustc_errors::DiagnosticBuilder;
use rustc_middle::dep_graph;
use rustc_middle::ich::StableHashingContext;
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
use rustc_middle::ty::query::{Providers, QueryEngine};
use rustc_middle::ty::{self, TyCtxt};
use rustc_serialize::opaque;
use rustc_span::Span;
#[macro_use]
@ -42,7 +45,8 @@ use rustc_query_system::query::QueryAccessors;
pub use rustc_query_system::query::QueryConfig;
pub(crate) use rustc_query_system::query::QueryDescription;
use rustc_middle::ty::query::on_disk_cache;
mod on_disk_cache;
pub use on_disk_cache::OnDiskCache;
mod profiling_support;
pub use self::profiling_support::alloc_self_profile_query_strings;

View File

@ -1,9 +1,4 @@
use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use crate::mir::{self, interpret};
use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use crate::ty::context::TyCtxt;
use crate::ty::{self, Ty};
use crate::QueryCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
use rustc_data_structures::thin_vec::ThinVec;
@ -12,6 +7,11 @@ use rustc_errors::Diagnostic;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::{self, interpret};
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::dep_graph::DepContext;
use rustc_query_system::query::QueryContext;
use rustc_serialize::{
@ -185,9 +185,8 @@ impl EncodedSourceFileId {
}
}
impl<'sess> OnDiskCache<'sess> {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
debug_assert!(sess.opts.incremental.is_some());
// Wrap in a scope so we can borrow `data`.
@ -228,7 +227,7 @@ impl<'sess> OnDiskCache<'sess> {
}
}
pub fn new_empty(source_map: &'sess SourceMap) -> Self {
fn new_empty(source_map: &'sess SourceMap) -> Self {
Self {
serialized_data: Vec::new(),
file_index_to_stable_id: Default::default(),
@ -249,11 +248,7 @@ impl<'sess> OnDiskCache<'sess> {
}
}
pub fn serialize<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
encoder: &mut FileEncoder,
) -> FileEncodeResult {
fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncodeResult {
// Serializing the `DepGraph` should not modify it.
tcx.dep_graph.with_ignore(|| {
// Allocate `SourceFileIndex`es.
@ -288,7 +283,7 @@ impl<'sess> OnDiskCache<'sess> {
// Do this *before* we clone 'latest_foreign_def_path_hashes', since
// loading existing queries may cause us to create new DepNodes, which
// may in turn end up invoking `store_foreign_def_id_hash`
tcx.queries.exec_cache_promotions(tcx);
tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx));
let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
let hygiene_encode_context = HygieneEncodeContext::default();
@ -311,7 +306,7 @@ impl<'sess> OnDiskCache<'sess> {
tcx.sess.time("encode_query_results", || -> FileEncodeResult {
let enc = &mut encoder;
let qri = &mut query_result_index;
tcx.queries.encode_query_results(tcx, enc, qri)
QueryCtxt::from_tcx(tcx).encode_query_results(enc, qri)
})?;
// Encode diagnostics.
@ -411,6 +406,88 @@ impl<'sess> OnDiskCache<'sess> {
})
}
fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option<DefId> {
let mut cache = self.def_path_hash_to_def_id_cache.lock();
match cache.entry(hash) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
debug!("def_path_hash_to_def_id({:?})", hash);
// Check if the `DefPathHash` corresponds to a definition in the current
// crate
if let Some(def_id) =
tcx.definitions_untracked().local_def_path_hash_to_def_id(hash)
{
let def_id = def_id.to_def_id();
e.insert(Some(def_id));
return Some(def_id);
}
// This `raw_def_id` represents the `DefId` of this `DefPathHash` in
// the *previous* compliation session. The `DefPathHash` includes the
// owning crate, so if the corresponding definition still exists in the
// current compilation session, the crate is guaranteed to be the same
// (otherwise, we would compute a different `DefPathHash`).
let raw_def_id = self.get_raw_def_id(&hash)?;
debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
// If the owning crate no longer exists, the corresponding definition definitely
// no longer exists.
let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
// If our `DefPathHash` corresponded to a definition in the local crate,
// we should have either found it in `local_def_path_hash_to_def_id`, or
// never attempted to load it in the first place. Any query result or `DepNode`
// that references a local `DefId` should depend on some HIR-related `DepNode`.
// If a local definition is removed/modified such that its old `DefPathHash`
// no longer has a corresponding definition, that HIR-related `DepNode` should
// end up red. This should prevent us from ever calling
// `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
// queries involved.
debug_assert_ne!(krate, LOCAL_CRATE);
// Try to find a definition in the current session, using the previous `DefIndex`
// as an initial guess.
let opt_def_id =
tcx.cstore_untracked().def_path_hash_to_def_id(krate, raw_def_id.index, hash);
debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
e.insert(opt_def_id);
opt_def_id
}
}
}
fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) {
// For reused dep nodes, we only need to store the mapping if the node
// is one whose query key we can reconstruct from the hash. We use the
// mapping to aid that reconstruction in the next session. While we also
// use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
// they're already registered during `DefId` encoding.
if dep_node.kind.can_reconstruct_query_key() {
let hash = DefPathHash(dep_node.hash.into());
// We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
// `latest_foreign_def_path_hashes`, since the `RawDefId` might have
// changed in the current compilation session (e.g. we've added/removed crates,
// or added/removed definitions before/after the target definition).
if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
if !def_id.is_local() {
self.store_foreign_def_id_hash(def_id, hash);
}
}
}
}
fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
// We may overwrite an existing entry, but it will have the same value,
// so it's fine
self.latest_foreign_def_path_hashes
.lock()
.insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
}
}
impl<'sess> OnDiskCache<'sess> {
pub fn as_dyn(&self) -> &dyn rustc_middle::ty::OnDiskCache<'sess> {
self as _
}
/// Loads a diagnostic emitted during the previous compilation session.
pub fn load_diagnostics(
&self,
@ -449,44 +526,6 @@ impl<'sess> OnDiskCache<'sess> {
cnum_map.get(&stable_crate_id).copied()
}
pub(crate) fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
// We may overwrite an existing entry, but it will have the same value,
// so it's fine
self.latest_foreign_def_path_hashes
.lock()
.insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
}
/// If the given `dep_node`'s hash still exists in the current compilation,
/// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
///
/// Normally, `store_foreign_def_id_hash` can be called directly by
/// the dependency graph when we construct a `DepNode`. However,
/// when we re-use a deserialized `DepNode` from the previous compilation
/// session, we only have the `DefPathHash` available. This method is used
/// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
/// out for usage in the next compilation session.
pub fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) {
// For reused dep nodes, we only need to store the mapping if the node
// is one whose query key we can reconstruct from the hash. We use the
// mapping to aid that reconstruction in the next session. While we also
// use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
// they're already registered during `DefId` encoding.
if dep_node.kind.can_reconstruct_query_key() {
let hash = DefPathHash(dep_node.hash.into());
// We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
// `latest_foreign_def_path_hashes`, since the `RawDefId` might have
// changed in the current compilation session (e.g. we've added/removed crates,
// or added/removed definitions before/after the target definition).
if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
if !def_id.is_local() {
self.store_foreign_def_id_hash(def_id, hash);
}
}
}
}
/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
pub fn try_load_query_result<'tcx, T>(
@ -579,63 +618,6 @@ impl<'sess> OnDiskCache<'sess> {
.collect()
})
}
/// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
/// session, if it still exists. This is used during incremental compilation to
/// turn a deserialized `DefPathHash` into its current `DefId`.
pub(crate) fn def_path_hash_to_def_id(
&self,
tcx: TyCtxt<'tcx>,
hash: DefPathHash,
) -> Option<DefId> {
let mut cache = self.def_path_hash_to_def_id_cache.lock();
match cache.entry(hash) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
debug!("def_path_hash_to_def_id({:?})", hash);
// Check if the `DefPathHash` corresponds to a definition in the current
// crate
if let Some(def_id) =
tcx.untracked_resolutions.definitions.local_def_path_hash_to_def_id(hash)
{
let def_id = def_id.to_def_id();
e.insert(Some(def_id));
return Some(def_id);
}
// This `raw_def_id` represents the `DefId` of this `DefPathHash` in
// the *previous* compliation session. The `DefPathHash` includes the
// owning crate, so if the corresponding definition still exists in the
// current compilation session, the crate is guaranteed to be the same
// (otherwise, we would compute a different `DefPathHash`).
let raw_def_id = self.get_raw_def_id(&hash)?;
debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
// If the owning crate no longer exists, the corresponding definition definitely
// no longer exists.
let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
// If our `DefPathHash` corresponded to a definition in the local crate,
// we should have either found it in `local_def_path_hash_to_def_id`, or
// never attempted to load it in the first place. Any query result or `DepNode`
// that references a local `DefId` should depend on some HIR-related `DepNode`.
// If a local definition is removed/modified such that its old `DefPathHash`
// no longer has a corresponding definition, that HIR-related `DepNode` should
// end up red. This should prevent us from ever calling
// `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
// queries involved.
debug_assert_ne!(krate, LOCAL_CRATE);
// Try to find a definition in the current session, using the previous `DefIndex`
// as an initial guess.
let opt_def_id = tcx.untracked_resolutions.cstore.def_path_hash_to_def_id(
krate,
raw_def_id.index,
hash,
);
debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
e.insert(opt_def_id);
opt_def_id
}
}
}
}
//- DECODING -------------------------------------------------------------------
@ -776,7 +758,7 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
}
}
crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
@ -827,7 +809,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
rustc_span::hygiene::register_local_expn_id(data, hash)
} else {
let index_guess = decoder.foreign_expn_data[&hash];
decoder.tcx.untracked_resolutions.cstore.expn_hash_to_expn_id(krate, index_guess, hash)
decoder.tcx.cstore_untracked().expn_hash_to_expn_id(krate, index_guess, hash)
};
#[cfg(debug_assertions)]

View File

@ -2,9 +2,8 @@
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.
use super::queries;
use crate::{on_disk_cache, queries, Queries};
use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::ty::query::on_disk_cache;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_query_system::dep_graph::HasDepContext;
@ -12,14 +11,16 @@ use rustc_query_system::query::{QueryContext, QueryDescription, QueryJobId, Quer
use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::Diagnostic;
use rustc_errors::{Diagnostic, Handler};
use rustc_serialize::opaque;
use rustc_span::def_id::LocalDefId;
use std::any::Any;
#[derive(Copy, Clone)]
pub struct QueryCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
pub queries: &'tcx super::Queries<'tcx>,
pub queries: &'tcx Queries<'tcx>,
}
impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
@ -83,14 +84,15 @@ impl QueryContext for QueryCtxt<'tcx> {
// Interactions with on_disk_cache
fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
self.on_disk_cache
self.queries
.on_disk_cache
.as_ref()
.map(|c| c.load_diagnostics(**self, prev_dep_node_index))
.unwrap_or_default()
}
fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec<Diagnostic>) {
if let Some(c) = self.on_disk_cache.as_ref() {
if let Some(c) = self.queries.on_disk_cache.as_ref() {
c.store_diagnostics(dep_node_index, diagnostics)
}
}
@ -100,7 +102,7 @@ impl QueryContext for QueryCtxt<'tcx> {
dep_node_index: DepNodeIndex,
diagnostics: ThinVec<Diagnostic>,
) {
if let Some(c) = self.on_disk_cache.as_ref() {
if let Some(c) = self.queries.on_disk_cache.as_ref() {
c.store_diagnostics_for_anon_node(dep_node_index, diagnostics)
}
}
@ -137,6 +139,22 @@ impl QueryContext for QueryCtxt<'tcx> {
}
impl<'tcx> QueryCtxt<'tcx> {
#[inline]
pub fn from_tcx(tcx: TyCtxt<'tcx>) -> Self {
let queries = tcx.queries.as_any();
let queries = unsafe {
let queries = std::mem::transmute::<&dyn Any, &dyn Any>(queries);
let queries = queries.downcast_ref().unwrap();
let queries = std::mem::transmute::<&Queries<'_>, &Queries<'_>>(queries);
queries
};
QueryCtxt { tcx, queries }
}
crate fn on_disk_cache(self) -> Option<&'tcx on_disk_cache::OnDiskCache<'tcx>> {
self.queries.on_disk_cache.as_ref()
}
pub(super) fn encode_query_results(
self,
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
@ -158,6 +176,15 @@ impl<'tcx> QueryCtxt<'tcx> {
Ok(())
}
pub fn try_print_query_stack(
self,
query: Option<QueryJobId<DepKind>>,
handler: &Handler,
num_frames: Option<usize>,
) -> usize {
rustc_query_system::query::print_query_stack(self, query, handler, num_frames)
}
}
/// This struct stores metadata about each Query.
@ -462,6 +489,8 @@ macro_rules! define_queries_struct {
local_providers: Box<Providers>,
extern_providers: Box<Providers>,
pub on_disk_cache: Option<OnDiskCache<$tcx>>,
$($(#[$attr])* $name: QueryState<
crate::dep_graph::DepKind,
query_keys::$name<$tcx>,
@ -472,10 +501,12 @@ macro_rules! define_queries_struct {
pub fn new(
local_providers: Providers,
extern_providers: Providers,
on_disk_cache: Option<OnDiskCache<$tcx>>,
) -> Self {
Queries {
local_providers: Box::new(local_providers),
extern_providers: Box::new(extern_providers),
on_disk_cache,
$($name: Default::default()),*
}
}
@ -501,43 +532,22 @@ macro_rules! define_queries_struct {
}
impl QueryEngine<'tcx> for Queries<'tcx> {
fn as_any(&'tcx self) -> &'tcx dyn std::any::Any {
let this = unsafe { std::mem::transmute::<&Queries<'_>, &Queries<'_>>(self) };
this as _
}
#[cfg(parallel_compiler)]
unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry) {
let tcx = QueryCtxt { tcx, queries: self };
rustc_query_system::query::deadlock(tcx, registry)
}
fn encode_query_results(
&'tcx self,
tcx: TyCtxt<'tcx>,
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
) -> opaque::FileEncodeResult {
let tcx = QueryCtxt { tcx, queries: self };
tcx.encode_query_results(encoder, query_result_index)
}
fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>) {
let tcx = QueryCtxt { tcx, queries: self };
tcx.dep_graph.exec_cache_promotions(tcx)
}
fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
let qcx = QueryCtxt { tcx, queries: self };
tcx.dep_graph.try_mark_green(qcx, dep_node).is_some()
}
fn try_print_query_stack(
&'tcx self,
tcx: TyCtxt<'tcx>,
query: Option<QueryJobId<dep_graph::DepKind>>,
handler: &Handler,
num_frames: Option<usize>,
) -> usize {
let qcx = QueryCtxt { tcx, queries: self };
rustc_query_system::query::print_query_stack(qcx, query, handler, num_frames)
}
$($(#[$attr])*
#[inline(always)]
fn $name(