diff --git a/Cargo.lock b/Cargo.lock index 9f43f5a8b36..ba76b310b2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3890,6 +3890,7 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_incremental", + "rustc_index", "rustc_lint", "rustc_metadata", "rustc_middle", diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index f3e4aab941b..210ba32bc1d 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -30,6 +30,7 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_metadata = { path = "../rustc_metadata" } rustc_mir = { path = "../rustc_mir" } rustc_mir_build = { path = "../rustc_mir_build" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ed5061125ba..76d988815ff 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -15,11 +15,13 @@ use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::Crate; +use rustc_index::vec::IndexVec; use rustc_lint::LintStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::middle; use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; +use rustc_middle::ty::query; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_mir as mir; @@ -738,20 +740,18 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(| extern_providers }); -pub struct QueryContext<'tcx>(&'tcx GlobalCtxt<'tcx>); +pub struct QueryContext<'tcx> { + gcx: &'tcx GlobalCtxt<'tcx>, +} impl<'tcx> QueryContext<'tcx> { pub fn enter(&mut self, f: F) -> R where F: FnOnce(TyCtxt<'tcx>) -> R, { - let icx = ty::tls::ImplicitCtxt::new(self.0); + let icx = ty::tls::ImplicitCtxt::new(self.gcx); ty::tls::enter_context(&icx, |_| f(icx.tcx)) } - - pub fn print_stats(&mut self) { - self.enter(ty::query::print_stats) - } } pub fn create_global_ctxt<'tcx>( @@ -762,6 +762,7 @@ pub fn create_global_ctxt<'tcx>( mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, + queries: &'tcx OnceCell>, global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { @@ -785,26 +786,33 @@ pub fn create_global_ctxt<'tcx>( callback(sess, &mut local_providers, &mut extern_providers); } + let queries = { + let crates = resolver_outputs.cstore.crates_untracked(); + let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); + let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); + providers[LOCAL_CRATE] = local_providers; + queries.get_or_init(|| query::Queries::new(providers, extern_providers)) + }; + let gcx = sess.time("setup_global_ctxt", || { global_ctxt.get_or_init(|| { TyCtxt::create_global_ctxt( sess, lint_store, - local_providers, - extern_providers, arena, resolver_outputs, krate, defs, dep_graph, query_result_on_disk_cache, + queries, &crate_name, &outputs, ) }) }); - QueryContext(gcx) + QueryContext { gcx } } /// Runs the resolution, type-checking, region checking and other diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index ac6b6d03115..86d78d7e9ca 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -13,6 +13,7 @@ use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; +use rustc_middle::ty::query; use rustc_middle::ty::{GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_serialize::json; use rustc_session::config::{self, OutputFilenames, OutputType}; @@ -71,6 +72,7 @@ impl Default for Query { pub struct Queries<'tcx> { compiler: &'tcx Compiler, gcx: OnceCell>, + queries: OnceCell>, arena: WorkerLocal>, hir_arena: WorkerLocal>, @@ -92,6 +94,7 @@ impl<'tcx> Queries<'tcx> { Queries { compiler, gcx: OnceCell::new(), + queries: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()), dep_graph_future: Default::default(), @@ -265,6 +268,7 @@ impl<'tcx> Queries<'tcx> { resolver_outputs.steal(), outputs, &crate_name, + &self.queries, &self.gcx, &self.arena, )) @@ -429,7 +433,7 @@ impl Compiler { } if self.session().opts.debugging_opts.query_stats { - gcx.print_stats(); + gcx.enter(query::print_stats); } } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 1ac71824faf..e387020d828 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -354,10 +354,9 @@ fn add_query_description_impl( quote! { #[inline] fn try_load_from_disk( - tcx: QueryCtxt<'tcx>, - id: SerializedDepNodeIndex + #tcx: QueryCtxt<'tcx>, + #id: SerializedDepNodeIndex ) -> Option { - let (#tcx, #id) = (*tcx, id); #block } } @@ -394,11 +393,10 @@ fn add_query_description_impl( #[inline] #[allow(unused_variables, unused_braces)] fn cache_on_disk( - tcx: QueryCtxt<'tcx>, - key: &Self::Key, - value: Option<&Self::Value> + #tcx: QueryCtxt<'tcx>, + #key: &Self::Key, + #value: Option<&Self::Value> ) -> bool { - let (#tcx, #key, #value) = (*tcx, key, value); #expr } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index ea1376e41c9..94a17f4645a 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -262,7 +262,7 @@ pub mod dep_kind { if let Some(key) = recover(tcx, dep_node) { force_query::, _>( - QueryCtxt(tcx), + QueryCtxt { tcx, queries: tcx.queries }, key, DUMMY_SP, *dep_node @@ -288,7 +288,8 @@ pub mod dep_kind { .unwrap_or(false)); let key = recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)); - if queries::$variant::cache_on_disk(QueryCtxt(tcx), &key, None) { + let qcx = QueryCtxt { tcx, queries: tcx.queries }; + if queries::$variant::cache_on_disk(qcx, &key, None) { let _ = tcx.$variant(key); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0f7728d48d9..343ae66c07a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -699,7 +699,7 @@ rustc_queries! { load_cached(tcx, id) { let typeck_results: Option> = tcx .on_disk_cache.as_ref() - .and_then(|c| c.try_load_query_result(tcx, id)); + .and_then(|c| c.try_load_query_result(*tcx, id)); typeck_results.map(|x| &*tcx.arena.alloc(x)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index fa176193a93..ec680eeb30f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -14,7 +14,7 @@ use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::traits; -use crate::ty::query::{self, OnDiskCache, TyCtxtAt}; +use crate::ty::query::{self, OnDiskCache, Queries, TyCtxtAt}; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts}; use crate::ty::TyKind::*; use crate::ty::{ @@ -968,7 +968,7 @@ pub struct GlobalCtxt<'tcx> { /// This is `None` if we are not incremental compilation mode pub(crate) on_disk_cache: Option>, - pub queries: query::Queries<'tcx>, + pub queries: &'tcx query::Queries<'tcx>, pub query_caches: query::QueryCaches<'tcx>, maybe_unused_trait_imports: FxHashSet, @@ -1109,14 +1109,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn create_global_ctxt( s: &'tcx Session, lint_store: Lrc, - local_providers: ty::query::Providers, - extern_providers: ty::query::Providers, arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, krate: &'tcx hir::Crate<'tcx>, definitions: &'tcx Definitions, dep_graph: DepGraph, on_disk_cache: Option>, + queries: &'tcx Queries<'tcx>, crate_name: &str, output_filenames: &OutputFilenames, ) -> GlobalCtxt<'tcx> { @@ -1128,10 +1127,6 @@ impl<'tcx> TyCtxt<'tcx> { let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); let cstore = resolutions.cstore; - let crates = cstore.crates_untracked(); - let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); - let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); - providers[LOCAL_CRATE] = local_providers; let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (hir_id, v) in krate.trait_map.iter() { @@ -1161,7 +1156,7 @@ impl<'tcx> TyCtxt<'tcx> { untracked_crate: krate, definitions, on_disk_cache, - queries: query::Queries::new(providers, extern_providers), + queries, query_caches: query::QueryCaches::default(), ty_rcache: Default::default(), pred_rcache: Default::default(), diff --git a/compiler/rustc_middle/src/ty/query/job.rs b/compiler/rustc_middle/src/ty/query/job.rs index 0ea8bcc9d9d..668109693a8 100644 --- a/compiler/rustc_middle/src/ty/query/job.rs +++ b/compiler/rustc_middle/src/ty/query/job.rs @@ -1,7 +1,4 @@ -use crate::ty::query::QueryCtxt; use crate::ty::tls; - -use rustc_query_system::query::deadlock; use rustc_rayon_core as rayon_core; use std::thread; @@ -21,7 +18,7 @@ pub unsafe fn handle_deadlock() { thread::spawn(move || { tls::enter_context(icx, |_| { rustc_span::SESSION_GLOBALS - .set(session_globals, || tls::with(|tcx| deadlock(QueryCtxt(tcx), ®istry))) + .set(session_globals, || tls::with(|tcx| tcx.queries.deadlock(tcx, ®istry))) }); }); } diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 88d1efffea7..4c0b5846741 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -44,6 +44,7 @@ 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::CrateDisambiguator; diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 5e862afae37..db3449ed2e2 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -133,7 +133,7 @@ struct Footer { foreign_def_path_hashes: UnhashMap, } -type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; +pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnostics = Vec; @@ -141,7 +141,7 @@ type EncodedDiagnostics = Vec; struct SourceFileIndex(u32); #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)] -struct AbsoluteBytePos(u32); +pub struct AbsoluteBytePos(u32); impl AbsoluteBytePos { fn new(pos: usize) -> AbsoluteBytePos { @@ -308,22 +308,7 @@ impl<'sess> OnDiskCache<'sess> { tcx.sess.time("encode_query_results", || -> FileEncodeResult { let enc = &mut encoder; let qri = &mut query_result_index; - - macro_rules! encode_queries { - ($($query:ident,)*) => { - $( - encode_query_results::>( - QueryCtxt(tcx), - enc, - qri - )?; - )* - } - } - - rustc_cached_queries!(encode_queries!); - - Ok(()) + tcx.queries.encode_query_results(tcx, enc, qri) })?; // Encode diagnostics. @@ -973,7 +958,7 @@ impl<'a, 'tcx> Decodable> for &'tcx [Span] { //- ENCODING ------------------------------------------------------------------- -trait OpaqueEncoder: Encoder { +pub trait OpaqueEncoder: Encoder { fn position(&self) -> usize; } @@ -985,7 +970,7 @@ impl OpaqueEncoder for FileEncoder { } /// An encoder that can write to the incremental compilation cache. -struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { +pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { tcx: TyCtxt<'tcx>, encoder: &'a mut E, type_shorthands: FxHashMap, usize>, @@ -1230,7 +1215,7 @@ impl<'a> Decodable> for IntEncodedWithFixedSize { } } -fn encode_query_results<'a, 'tcx, Q>( +pub fn encode_query_results<'a, 'tcx, Q>( tcx: QueryCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, query_result_index: &mut EncodedQueryResultIndex, diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs index b084fd01327..1d4be770005 100644 --- a/compiler/rustc_middle/src/ty/query/plumbing.rs +++ b/compiler/rustc_middle/src/ty/query/plumbing.rs @@ -2,7 +2,7 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::ty::query::Query; +use crate::ty::query::{on_disk_cache, Query}; use crate::ty::tls::{self, ImplicitCtxt}; use crate::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::HasDepContext; @@ -13,17 +13,21 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level}; +use rustc_serialize::opaque; use rustc_span::def_id::DefId; use rustc_span::Span; #[derive(Copy, Clone)] -pub struct QueryCtxt<'tcx>(pub TyCtxt<'tcx>); +pub struct QueryCtxt<'tcx> { + pub tcx: TyCtxt<'tcx>, + pub queries: &'tcx super::Queries<'tcx>, +} impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> { type Target = TyCtxt<'tcx>; fn deref(&self) -> &Self::Target { - &self.0 + &self.tcx } } @@ -34,7 +38,7 @@ impl HasDepContext for QueryCtxt<'tcx> { #[inline] fn dep_context(&self) -> &Self::DepContext { - &self.0 + &self.tcx } } @@ -49,7 +53,7 @@ impl QueryContext for QueryCtxt<'tcx> { } fn def_path_str(&self, def_id: DefId) -> String { - self.0.def_path_str(def_id) + self.tcx.def_path_str(def_id) } fn current_query_job(&self) -> Option> { @@ -142,6 +146,28 @@ impl<'tcx> QueryCtxt<'tcx> { err }) } + + pub(super) fn encode_query_results( + self, + encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>, + query_result_index: &mut on_disk_cache::EncodedQueryResultIndex, + ) -> opaque::FileEncodeResult { + macro_rules! encode_queries { + ($($query:ident,)*) => { + $( + on_disk_cache::encode_query_results::>( + self, + encoder, + query_result_index + )?; + )* + } + } + + rustc_cached_queries!(encode_queries!); + + Ok(()) + } } impl<'tcx> TyCtxt<'tcx> { @@ -174,7 +200,10 @@ impl<'tcx> TyCtxt<'tcx> { "#{} [{}] {}", i, query_info.info.query.name(), - query_info.info.query.describe(QueryCtxt(icx.tcx)) + query_info + .info + .query + .describe(QueryCtxt { tcx: icx.tcx, queries: icx.tcx.queries }) ), ); diag.span = @@ -570,7 +599,7 @@ macro_rules! define_queries_struct { } impl<$tcx> Queries<$tcx> { - pub(crate) fn new( + pub fn new( providers: IndexVec, fallback_extern_providers: Providers, ) -> Self { @@ -597,17 +626,33 @@ macro_rules! define_queries_struct { Some(jobs) } + #[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) + } + + pub(crate) 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) + } + $($(#[$attr])* #[inline(always)] fn $name( - &self, + &'tcx self, tcx: TyCtxt<$tcx>, span: Span, key: query_keys::$name<$tcx>, lookup: QueryLookup, mode: QueryMode, ) -> Option> { - let qcx = QueryCtxt(tcx); + let qcx = QueryCtxt { tcx, queries: self }; get_query::, _>(qcx, span, key, lookup, mode) })* }