mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Move OnDiskCache to rustc_query_impl.
This commit is contained in:
parent
68511b574f
commit
81241cbf3a
@ -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",
|
||||
]
|
||||
|
@ -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())),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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,
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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)]
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user