From 43bb31b9540a439dcca65f47b8644eafe4a42e2d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 12 Jul 2021 22:19:25 +0200 Subject: [PATCH 01/12] Allow to create definitions inside the query system. --- .../src/debuginfo/metadata/type_map.rs | 5 +- .../src/debuginfo/type_names.rs | 20 ++-- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_data_structures/src/sync.rs | 27 +++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 23 ++-- compiler/rustc_middle/src/dep_graph/mod.rs | 4 +- compiler/rustc_middle/src/hir/map/mod.rs | 62 +++++----- compiler/rustc_middle/src/query/mod.rs | 6 + compiler/rustc_middle/src/ty/context.rs | 113 +++++++++++++++--- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/util.rs | 10 +- .../rustc_mir_transform/src/coverage/mod.rs | 9 +- compiler/rustc_mir_transform/src/inline.rs | 2 +- compiler/rustc_query_impl/src/keys.rs | 11 ++ .../rustc_query_impl/src/on_disk_cache.rs | 9 +- compiler/rustc_query_impl/src/plumbing.rs | 11 +- .../src/dep_graph/dep_node.rs | 11 +- .../rustc_query_system/src/dep_graph/graph.rs | 6 +- .../rustc_query_system/src/dep_graph/mod.rs | 2 +- compiler/rustc_query_system/src/ich/hcx.rs | 1 + .../rustc_query_system/src/query/plumbing.rs | 3 +- compiler/rustc_symbol_mangling/src/legacy.rs | 73 +++++------ .../passes/check_code_block_syntax.rs | 3 +- 23 files changed, 263 insertions(+), 153 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 87fbb737ea8a9..8fc8118849bae 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -93,8 +93,9 @@ impl<'tcx> UniqueTypeId<'tcx> { /// Right now this takes the form of a hex-encoded opaque hash value. pub fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { let mut hasher = StableHasher::new(); - let mut hcx = tcx.create_stable_hashing_context(); - hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)); + tcx.with_stable_hashing_context(|mut hcx| { + hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)) + }); hasher.finish::().to_hex() } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 8755d91818d22..8cd5a0fc24759 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -701,16 +701,20 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // If we cannot evaluate the constant to a known type, we fall back // to emitting a stable hash value of the constant. This isn't very pretty // but we get a deterministic, virtually unique value for the constant. - let hcx = &mut tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - let ct = ct.eval(tcx, ty::ParamEnv::reveal_all()); - hcx.while_hashing_spans(false, |hcx| ct.to_valtree().hash_stable(hcx, &mut hasher)); + // // Let's only emit 64 bits of the hash value. That should be plenty for // avoiding collisions and will make the emitted type names shorter. - // Note: Don't use `StableHashResult` impl of `u64` here directly, since that - // would lead to endianness problems. - let hash: u128 = hasher.finish(); - let hash_short = (hash.to_le() as u64).to_le(); + let hash_short = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + let ct = ct.eval(tcx, ty::ParamEnv::reveal_all()); + hcx.while_hashing_spans(false, |hcx| { + ct.to_valtree().hash_stable(hcx, &mut hasher) + }); + // Note: Don't use `StableHashResult` impl of `u64` here directly, since that + // would lead to endianness problems. + let hash: u128 = hasher.finish(); + (hash.to_le() as u64).to_le() + }); if cpp_like_debuginfo(tcx) { write!(output, "CONST${:x}", hash_short) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 390a44d3f337d..0a2d2b4070904 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,6 +10,7 @@ #![feature(array_windows)] #![feature(associated_type_bounds)] #![feature(auto_traits)] +#![feature(cell_leak)] #![feature(control_flow_enum)] #![feature(extend_one)] #![feature(let_else)] diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 4437c0b1b6964..cf0940df9e487 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -539,6 +539,33 @@ impl RwLock { pub fn borrow_mut(&self) -> WriteGuard<'_, T> { self.write() } + + #[cfg(not(parallel_compiler))] + #[inline(always)] + pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> { + ReadGuard::clone(rg) + } + + #[cfg(parallel_compiler)] + #[inline(always)] + pub fn clone_guard<'a>(rg: &ReadGuard<'a, T>) -> ReadGuard<'a, T> { + ReadGuard::rwlock(&rg).read() + } + + #[cfg(not(parallel_compiler))] + #[inline(always)] + pub fn leak(&self) -> &T { + ReadGuard::leak(self.read()) + } + + #[cfg(parallel_compiler)] + #[inline(always)] + pub fn leak(&self) -> &T { + let guard = self.read(); + let ret = unsafe { &*(&*guard as *const T) }; + std::mem::forget(guard); + ret + } } // FIXME: Probably a bad idea diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index bb4b502bded45..7e07898ff52f1 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_table(&mut self) { - let table = self.tcx.definitions_untracked().def_path_table(); + let table = self.tcx.def_path_table(); if self.is_proc_macro { for def_index in std::iter::once(CRATE_DEF_INDEX) .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)) @@ -443,9 +443,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_hash_map(&mut self) -> LazyValue> { - self.lazy(DefPathHashMapRef::BorrowedFromTcx( - self.tcx.definitions_untracked().def_path_hash_to_def_index_map(), - )) + self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } fn encode_source_map(&mut self) -> LazyArray { @@ -614,7 +612,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let interpret_alloc_index_bytes = self.position() - i; // Encode the proc macro data. This affects 'tables', - // so we need to do this before we encode the tables + // so we need to do this before we encode the tables. + // This overwrites def_keys, so it must happen after encode_def_path_table. i = self.position(); let proc_macro_data = self.encode_proc_macros(); let proc_macro_data_bytes = self.position() - i; @@ -992,8 +991,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return; } let tcx = self.tcx; - let hir = tcx.hir(); - for local_id in hir.iter_local_def_id() { + for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.opt_def_kind(local_id); let Some(def_kind) = def_kind else { continue }; @@ -1854,12 +1852,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_traits_and_impls()"); empty_proc_macro!(self); let tcx = self.tcx; - let mut ctx = tcx.create_stable_hashing_context(); let mut all_impls: Vec<_> = tcx.crate_inherent_impls(()).incoherent_impls.iter().collect(); - all_impls.sort_by_cached_key(|&(&simp, _)| { - let mut hasher = StableHasher::new(); - simp.hash_stable(&mut ctx, &mut hasher); - hasher.finish::(); + tcx.with_stable_hashing_context(|mut ctx| { + all_impls.sort_by_cached_key(|&(&simp, _)| { + let mut hasher = StableHasher::new(); + simp.hash_stable(&mut ctx, &mut hasher); + hasher.finish::() + }) }); let all_impls: Vec<_> = all_impls .into_iter() diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index e335cb395f84f..5f3f1a3bc6c3a 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -71,8 +71,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { type DepKind = DepKind; #[inline] - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - TyCtxt::create_stable_hashing_context(*self) + fn with_stable_hashing_context(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R { + TyCtxt::with_stable_hashing_context(*self, f) } #[inline] diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 3539acbc06ee9..3ac302ef0ed35 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -218,13 +218,6 @@ impl<'hir> Map<'hir> { self.tcx.local_def_id_to_hir_id(def_id) } - pub fn iter_local_def_id(self) -> impl Iterator + 'hir { - // Create a dependency to the crate to be sure we re-execute this when the amount of - // definitions change. - self.tcx.ensure().hir_crate(()); - self.tcx.definitions_untracked().iter_local_def_id() - } - /// Do not call this function directly. The query should be called. pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option { let hir_id = self.local_def_id_to_hir_id(local_def_id); @@ -1141,34 +1134,35 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { source_file_names.sort_unstable(); - let mut hcx = tcx.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); - upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); - source_file_names.hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.debugging_opts.incremental_relative_spans { - let definitions = &tcx.definitions_untracked(); - let mut owner_spans: Vec<_> = krate - .owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let _ = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); - let span = resolutions.source_span[def_id]; - debug_assert_eq!(span.parent(), None); - Some((def_path_hash, span)) - }) - .collect(); - owner_spans.sort_unstable_by_key(|bn| bn.0); - owner_spans.hash_stable(&mut hcx, &mut stable_hasher); - } - tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); - // Hash visibility information since it does not appear in HIR. - resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); - resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); + upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); + source_file_names.hash_stable(&mut hcx, &mut stable_hasher); + if tcx.sess.opts.debugging_opts.incremental_relative_spans { + let definitions = tcx.definitions_untracked(); + let mut owner_spans: Vec<_> = krate + .owners + .iter_enumerated() + .filter_map(|(def_id, info)| { + let _ = info.as_owner()?; + let def_path_hash = definitions.def_path_hash(def_id); + let span = resolutions.source_span[def_id]; + debug_assert_eq!(span.parent(), None); + Some((def_path_hash, span)) + }) + .collect(); + owner_spans.sort_unstable_by_key(|bn| bn.0); + owner_spans.hash_stable(&mut hcx, &mut stable_hasher); + } + tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); + // Hash visibility information since it does not appear in HIR. + resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); + resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); - let crate_hash: Fingerprint = stable_hasher.finish(); Svh::new(crate_hash.to_smaller_hash()) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 57c4f3f3ba392..abc639136d6d2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -20,6 +20,12 @@ rustc_queries! { desc { "trigger a delay span bug" } } + /// Create a new definition within the incr. comp. engine. + query register_def(_: ty::RawLocalDefId) -> LocalDefId { + eval_always + desc { "register a DefId with the incr. comp. engine" } + } + query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { eval_always no_hash diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index af071b4e93903..60329fc6eea40 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -32,12 +32,13 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal}; use rustc_data_structures::vec_map::VecMap; use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -122,6 +123,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PlaceholderRegion = ty::PlaceholderRegion; } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub struct RawLocalDefId(LocalDefId); + /// 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)] @@ -1069,7 +1073,7 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, - definitions: rustc_hir::definitions::Definitions, + definitions: RwLock, cstore: Box, /// Output of the resolver. @@ -1233,7 +1237,7 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, lint_store: Lrc, arena: &'tcx WorkerLocal>, - definitions: rustc_hir::definitions::Definitions, + definitions: Definitions, cstore: Box, untracked_resolutions: ty::ResolverOutputs, krate: &'tcx hir::Crate<'tcx>, @@ -1265,7 +1269,7 @@ impl<'tcx> TyCtxt<'tcx> { arena, interners, dep_graph, - definitions, + definitions: RwLock::new(definitions), cstore, untracked_resolutions, prof: s.prof.clone(), @@ -1368,7 +1372,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey { // Accessing the DefKey is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.definitions.def_key(id) + self.definitions_untracked().def_key(id) } else { self.cstore.def_key(id) } @@ -1382,7 +1386,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath { // Accessing the DefPath is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.definitions.def_path(id) + self.definitions_untracked().def_path(id) } else { self.cstore.def_path(id) } @@ -1392,7 +1396,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash { // Accessing the DefPathHash is ok, it is incr. comp. stable. if let Some(def_id) = def_id.as_local() { - self.definitions.def_path_hash(def_id) + self.definitions_untracked().def_path_hash(def_id) } else { self.cstore.def_path_hash(def_id) } @@ -1429,7 +1433,7 @@ impl<'tcx> TyCtxt<'tcx> { // If this is a DefPathHash from the local crate, we can look up the // DefId in the tcx's `Definitions`. if stable_crate_id == self.sess.local_stable_crate_id() { - self.definitions.local_def_path_hash_to_def_id(hash, err).to_def_id() + self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id() } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. @@ -1460,6 +1464,65 @@ impl<'tcx> TyCtxt<'tcx> { ) } + /// Create a new definition within the incr. comp. engine. + pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) -> LocalDefId { + // The following call has the side effect of modifying the tables inside `definitions`. + // These very tables are relied on by the incr. comp. engine to decode DepNodes and to + // decode the on-disk cache. + let def_id = self.definitions.write().create_def(parent, data); + + // We need to ensure that these side effects are re-run by the incr. comp. engine. + // When the incr. comp. engine considers marking this query as green, eval_always requires + // we run the function to run. To invoke it, the parameter cannot be reconstructed from + // the DepNode, so the caller query is run. Luckily, we are inside the caller query, + // therefore the definition is properly created. + debug_assert!({ + use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; + self.is_eval_always(crate::dep_graph::DepKind::register_def) + && !>>::fingerprint_style() + .reconstructible() + }); + + // Any LocalDefId which is used within queries, either as key or result, either: + // - has been created before the construction of the TyCtxt; + // - has been created by this call to `register_def`. + // As a consequence, this LocalDefId is always re-created before it is needed by the incr. + // comp. engine itself. + self.register_def(RawLocalDefId(def_id)) + } + + pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { + // Create a dependency to the crate to be sure we re-execute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.iter_local_def_id() + } + + pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.def_path_table() + } + + pub fn def_path_hash_to_def_index_map( + self, + ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap { + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.ensure().hir_crate(()); + // Leak a read lock once we start iterating on definitions, to prevent adding new onces + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.definitions.leak(); + definitions.def_path_hash_to_def_index_map() + } + /// 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 CrateStoreDyn { @@ -1468,8 +1531,9 @@ impl<'tcx> TyCtxt<'tcx> { /// 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.definitions + #[inline] + pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> { + self.definitions.read() } /// Note that this is *untracked* and should only be used within the query @@ -1480,23 +1544,33 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline(always)] - pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - StableHashingContext::new( + pub fn with_stable_hashing_context( + self, + f: impl FnOnce(StableHashingContext<'_>) -> R, + ) -> R { + let definitions = self.definitions_untracked(); + let hcx = StableHashingContext::new( self.sess, - &self.definitions, + &*definitions, &*self.cstore, &self.untracked_resolutions.source_span, - ) + ); + f(hcx) } #[inline(always)] - pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> { - StableHashingContext::ignore_spans( + pub fn with_no_span_stable_hashing_context( + self, + f: impl FnOnce(StableHashingContext<'_>) -> R, + ) -> R { + let definitions = self.definitions_untracked(); + let hcx = StableHashingContext::ignore_spans( self.sess, - &self.definitions, + &*definitions, &*self.cstore, &self.untracked_resolutions.source_span, - ) + ); + f(hcx) } pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult { @@ -2304,7 +2378,7 @@ impl<'tcx> TyCtxt<'tcx> { self.interners.intern_ty( st, self.sess, - &self.definitions, + &self.definitions.read(), &*self.cstore, // This is only used to create a stable hashing context. &self.untracked_resolutions.source_span, @@ -2953,4 +3027,5 @@ pub fn provide(providers: &mut ty::query::Providers) { // We want to check if the panic handler was defined in this crate tcx.lang_items().panic_impl().map_or(false, |did| did.is_local()) }; + providers.register_def = |_, raw_id| raw_id.0; } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3a795af2121d0..e00cf3ff9bebc 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -72,8 +72,8 @@ pub use self::consts::{ pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData, - GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, - UserTypeAnnotationIndex, + GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, RawLocalDefId, TyCtxt, + TypeckResults, UserType, UserTypeAnnotationIndex, }; pub use self::instance::{Instance, InstanceDef}; pub use self::list::List; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3a876df84c287..0e581d7f1f7ed 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -142,16 +142,16 @@ impl<'tcx> TyCtxt<'tcx> { /// Creates a hash of the type `Ty` which will be the same no matter what crate /// context it's calculated within. This is used by the `type_id` intrinsic. pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { - let mut hasher = StableHasher::new(); - let mut hcx = self.create_stable_hashing_context(); - // We want the type_id be independent of the types free regions, so we // erase them. The erase_regions() call will also anonymize bound // regions, which is desirable too. let ty = self.erase_regions(ty); - hcx.while_hashing_spans(false, |hcx| ty.hash_stable(hcx, &mut hasher)); - hasher.finish() + self.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| ty.hash_stable(hcx, &mut hasher)); + hasher.finish() + }) } pub fn res_generics_def_id(self, res: Res) -> Option { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 782b620e28fe0..88ad5b7ef1482 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -15,7 +15,6 @@ use spans::{CoverageSpan, CoverageSpans}; use crate::MirPass; use rustc_data_structures::graph::WithNumNodes; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; use rustc_middle::hir; @@ -576,12 +575,6 @@ fn get_body_span<'tcx>( fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. - let mut hcx = tcx.create_no_span_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); let owner = hir_body.id().hir_id.owner; - let bodies = &tcx.hir_owner_nodes(owner).unwrap().bodies; - hcx.with_hir_bodies(false, owner, bodies, |hcx| { - hir_body.value.hash_stable(hcx, &mut stable_hasher) - }); - stable_hasher.finish() + tcx.hir_owner_nodes(owner).unwrap().hash_including_bodies.to_smaller_hash() } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 12f5764152e56..8f049a182eeaf 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -588,7 +588,7 @@ impl<'tcx> Inliner<'tcx> { ); expn_data.def_site = callee_body.span; let expn_data = - LocalExpnId::fresh(expn_data, self.tcx.create_stable_hashing_context()); + self.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); let mut integrator = Integrator { args: &args, new_locals: Local::new(caller_body.local_decls.len()).., diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 6fbafeb1d32b3..c3fbba4456e1e 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -39,6 +39,17 @@ impl Key for () { } } +impl Key for ty::RawLocalDefId { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for ty::InstanceDef<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index b01c512a3b439..4c25075327f01 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -653,12 +653,11 @@ impl<'a, 'tcx> Decodable> for ExpnId { #[cfg(debug_assertions)] { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - let mut hcx = decoder.tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - hcx.while_hashing_spans(true, |hcx| { - expn_id.expn_data().hash_stable(hcx, &mut hasher) + let local_hash: u64 = decoder.tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + expn_id.expn_data().hash_stable(&mut hcx, &mut hasher); + hasher.finish() }); - let local_hash: u64 = hasher.finish(); debug_assert_eq!(hash.local_hash(), local_hash); } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 3ed6632ba66ad..d0fef364eafd8 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -291,11 +291,12 @@ macro_rules! define_queries { .and_then(|def_id| tcx.opt_def_kind(def_id)) }; let hash = || { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() + tcx.with_stable_hashing_context(|mut hcx|{ + let mut hasher = StableHasher::new(); + std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher); + key.hash_stable(&mut hcx, &mut hasher); + hasher.finish::() + }) }; QueryStackFrame::new(name, description, span, def_kind, hash) diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index bb2179a24953b..c6210095b60fc 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -131,12 +131,11 @@ where #[inline(always)] default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - - self.hash_stable(&mut hcx, &mut hasher); - - hasher.finish() + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }) } #[inline(always)] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 341cf8f827bc9..0e1419f8a483a 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -328,10 +328,8 @@ impl DepGraph { let dcx = cx.dep_context(); let hashing_timer = dcx.profiler().incr_result_hashing(); - let current_fingerprint = hash_result.map(|f| { - let mut hcx = dcx.create_stable_hashing_context(); - f(&mut hcx, &result) - }); + let current_fingerprint = + hash_result.map(|f| dcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, &result))); let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 5907ae309ca37..345ada263e4d2 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -23,7 +23,7 @@ pub trait DepContext: Copy { type DepKind: self::DepKind; /// Create a hashing context for hashing new results. - fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; + fn with_stable_hashing_context(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; /// Access the DepGraph. fn dep_graph(&self) -> &DepGraph; diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 62a1f776fb352..89b9a80ee4dfa 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,4 +1,5 @@ use crate::ich; + use rustc_ast as ast; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3e4c7ad9f8f41..bbcd00be943a2 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -542,8 +542,7 @@ fn incremental_verify_ich( debug!("BEGIN verify_ich({:?})", dep_node); let new_hash = query.hash_result.map_or(Fingerprint::ZERO, |f| { - let mut hcx = tcx.create_stable_hashing_context(); - f(&mut hcx, result) + tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) }); let old_hash = tcx.dep_graph().prev_fingerprint_of(dep_node); debug!("END verify_ich({:?})", dep_node); diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 470438471cb96..e3045c9321d1c 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -96,47 +96,48 @@ fn get_symbol_hash<'tcx>( let substs = instance.substs; debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs); - let mut hasher = StableHasher::new(); - let mut hcx = tcx.create_stable_hashing_context(); - - record_time(&tcx.sess.perf_stats.symbol_hash_time, || { - // the main symbol name is not necessarily unique; hash in the - // compiler's internal def-path, guaranteeing each symbol has a - // truly unique path - tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); - - // Include the main item-type. Note that, in this case, the - // assertions about `needs_subst` may not hold, but this item-type - // ought to be the same for every reference anyway. - assert!(!item_type.has_erasable_regions()); - hcx.while_hashing_spans(false, |hcx| { - item_type.hash_stable(hcx, &mut hasher); - - // If this is a function, we hash the signature as well. - // This is not *strictly* needed, but it may help in some - // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::FnDef(..) = item_type.kind() { - item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); - } + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + + record_time(&tcx.sess.perf_stats.symbol_hash_time, || { + // the main symbol name is not necessarily unique; hash in the + // compiler's internal def-path, guaranteeing each symbol has a + // truly unique path + tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); + + // Include the main item-type. Note that, in this case, the + // assertions about `needs_subst` may not hold, but this item-type + // ought to be the same for every reference anyway. + assert!(!item_type.has_erasable_regions()); + hcx.while_hashing_spans(false, |hcx| { + item_type.hash_stable(hcx, &mut hasher); + + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::FnDef(..) = item_type.kind() { + item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); + } - // also include any type parameters (for generic items) - substs.hash_stable(hcx, &mut hasher); + // also include any type parameters (for generic items) + substs.hash_stable(hcx, &mut hasher); - if let Some(instantiating_crate) = instantiating_crate { - tcx.def_path_hash(instantiating_crate.as_def_id()) - .stable_crate_id() - .hash_stable(hcx, &mut hasher); - } + if let Some(instantiating_crate) = instantiating_crate { + tcx.def_path_hash(instantiating_crate.as_def_id()) + .stable_crate_id() + .hash_stable(hcx, &mut hasher); + } - // We want to avoid accidental collision between different types of instances. - // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original - // instances without this. - discriminant(&instance.def).hash_stable(hcx, &mut hasher); + // We want to avoid accidental collision between different types of instances. + // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original + // instances without this. + discriminant(&instance.def).hash_stable(hcx, &mut hasher); + }); }); - }); - // 64 bits should be enough to avoid collisions. - hasher.finish::() + // 64 bits should be enough to avoid collisions. + hasher.finish::() + }) } // Follow C++ namespace-mangling style, see diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 8bf0971ccb5a5..0172ef5700b62 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -53,7 +53,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { None, None, ); - let expn_id = LocalExpnId::fresh(expn_data, self.cx.tcx.create_stable_hashing_context()); + let expn_id = + self.cx.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx)); let span = DUMMY_SP.fresh_expansion(expn_id); let is_empty = rustc_driver::catch_fatal_errors(|| { From 250c71b85d0eed22982ef2b2db92fd5e63772c42 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 13 Jul 2021 18:45:20 +0200 Subject: [PATCH 02/12] Make AST lowering a query. --- Cargo.lock | 1 + compiler/rustc_ast_lowering/src/item.rs | 24 ++-- compiler/rustc_ast_lowering/src/lib.rs | 138 +++++++++------------ compiler/rustc_hir/Cargo.toml | 1 + compiler/rustc_hir/src/arena.rs | 2 +- compiler/rustc_hir/src/lib.rs | 4 + compiler/rustc_interface/src/passes.rs | 53 +------- compiler/rustc_interface/src/queries.rs | 10 +- compiler/rustc_lint/src/late.rs | 2 +- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 9 +- compiler/rustc_middle/src/ty/context.rs | 16 ++- compiler/rustc_query_system/src/ich/hcx.rs | 12 +- 14 files changed, 111 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75b9c0fce2295..86936b25d8ad9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3869,6 +3869,7 @@ name = "rustc_hir" version = "0.0.0" dependencies = [ "odht", + "rustc_arena", "rustc_ast", "rustc_data_structures", "rustc_error_messages", diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 0ef213716945c..3acca74a4cd92 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,7 +1,6 @@ use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; -use super::{LoweringContext, ParamMode}; -use crate::{Arena, FnDeclKind}; +use super::{FnDeclKind, LoweringContext, ParamMode}; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; @@ -12,12 +11,9 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; -use rustc_hir::definitions::Definitions; use rustc_hir::PredicateOrigin; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::ty::{ResolverAstLowering, ResolverOutputs}; -use rustc_session::cstore::CrateStoreDyn; -use rustc_session::Session; +use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -27,12 +23,8 @@ use smallvec::{smallvec, SmallVec}; use std::iter; pub(super) struct ItemLowerer<'a, 'hir> { - pub(super) sess: &'a Session, - pub(super) definitions: &'a mut Definitions, - pub(super) cstore: &'a CrateStoreDyn, - pub(super) resolutions: &'a ResolverOutputs, + pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, - pub(super) arena: &'hir Arena<'hir>, pub(super) ast_index: &'a IndexVec>, pub(super) owners: &'a mut IndexVec>>, } @@ -65,12 +57,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { ) { let mut lctx = LoweringContext { // Pseudo-globals. - sess: &self.sess, - definitions: self.definitions, - cstore: self.cstore, - resolutions: self.resolutions, + tcx: self.tcx, + sess: &self.tcx.sess, resolver: self.resolver, - arena: self.arena, + arena: self.tcx.hir_arena, // HirId handling. bodies: Vec::new(), @@ -145,7 +135,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { let def_id = self.resolver.node_id_to_def_id[&item.id]; let parent_id = { - let parent = self.definitions.def_key(def_id).parent; + let parent = self.tcx.hir().def_key(def_id).parent; let local_def_index = parent.unwrap(); LocalDefId { local_def_index } }; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e8b92eaad5c8d..ee978f39d2263 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -53,12 +53,10 @@ use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; -use rustc_hir::definitions::{DefPathData, Definitions}; +use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::ty::{ResolverAstLowering, ResolverOutputs}; -use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::CrateStoreDyn; +use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::hygiene::MacroKind; @@ -83,19 +81,13 @@ mod item; mod pat; mod path; -rustc_hir::arena_types!(rustc_arena::declare_arena); - -struct LoweringContext<'a, 'hir: 'a> { - /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. - sess: &'a Session, - - definitions: &'a mut Definitions, - cstore: &'a CrateStoreDyn, - resolutions: &'a ResolverOutputs, +struct LoweringContext<'a, 'hir> { + tcx: TyCtxt<'hir>, + sess: &'hir Session, resolver: &'a mut ResolverAstLowering, /// Used to allocate HIR nodes. - arena: &'hir Arena<'hir>, + arena: &'hir hir::Arena<'hir>, /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, @@ -391,61 +383,58 @@ fn index_crate<'a>( /// Compute the hash for the HIR of the full crate. /// This hash will then be part of the crate_hash which is stored in the metadata. fn compute_hir_hash( - sess: &Session, - definitions: &Definitions, - cstore: &CrateStoreDyn, - resolver: &ResolverOutputs, + tcx: TyCtxt<'_>, owners: &IndexVec>>, ) -> Fingerprint { let mut hir_body_nodes: Vec<_> = owners .iter_enumerated() .filter_map(|(def_id, info)| { let info = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); + let def_path_hash = tcx.hir().def_path_hash(def_id); Some((def_path_hash, info)) }) .collect(); hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - let mut stable_hasher = StableHasher::new(); - let mut hcx = StableHashingContext::new(sess, definitions, cstore, &resolver.source_span); - hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() + tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }) } -pub fn lower_crate<'hir>( - sess: &Session, - krate: &Crate, - definitions: &mut Definitions, - cstore: &CrateStoreDyn, - resolutions: &ResolverOutputs, - mut resolver: ResolverAstLowering, - arena: &'hir Arena<'hir>, -) -> &'hir hir::Crate<'hir> { - let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); +pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { + let sess = tcx.sess; + let krate = tcx.untracked_crate.steal(); + let mut resolver = tcx.resolver_for_lowering(()).steal(); - let ast_index = index_crate(&resolver.node_id_to_def_id, krate); - - let mut owners = - IndexVec::from_fn_n(|_| hir::MaybeOwner::Phantom, definitions.def_index_count()); + let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); + let mut owners = IndexVec::from_fn_n( + |_| hir::MaybeOwner::Phantom, + tcx.definitions_untracked().def_index_count(), + ); for def_id in ast_index.indices() { item::ItemLowerer { - sess, - definitions, - cstore, - resolutions, + tcx, resolver: &mut resolver, - arena, ast_index: &ast_index, owners: &mut owners, } .lower_node(def_id); } - let hir_hash = compute_hir_hash(sess, definitions, cstore, resolutions, &owners); - let krate = hir::Crate { owners, hir_hash }; - arena.alloc(krate) + // Drop AST to free memory + std::mem::drop(ast_index); + sess.time("drop_ast", || std::mem::drop(krate)); + + // Discard hygiene data, which isn't required after lowering to HIR. + if !sess.opts.debugging_opts.keep_hygiene_data { + rustc_span::hygiene::clear_syntax_context_map(); + } + + let hir_hash = compute_hir_hash(tcx, &owners); + hir::Crate { owners, hir_hash } } #[derive(Copy, Clone, PartialEq, Debug)] @@ -464,15 +453,6 @@ enum ParenthesizedGenericArgs { } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - StableHashingContext::new( - self.sess, - self.definitions, - self.cstore, - &self.resolutions.source_span, - ) - } - fn create_def( &mut self, parent: LocalDefId, @@ -484,10 +464,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.definitions.def_key(self.local_def_id(node_id)), + self.tcx.hir().def_key(self.local_def_id(node_id)), ); - let def_id = self.definitions.create_def(parent, data); + let def_id = self.tcx.create_def(parent, data); // Some things for which we allocate `LocalDefId`s don't correspond to // anything in the AST, so they don't have a `NodeId`. For these cases @@ -578,7 +558,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bodies.sort_by_key(|(k, _)| *k); let bodies = SortedMap::from_presorted_elements(bodies); let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies); - let (nodes, parenting) = index::index_hir(self.sess, self.definitions, node, &bodies); + let (nodes, parenting) = + index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies); let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, @@ -587,10 +568,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { local_id_to_def_id, }; let attrs = { - let mut hcx = self.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - attrs.hash_stable(&mut hcx, &mut stable_hasher); - let hash = stable_hasher.finish(); + let hash = self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + attrs.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + }); hir::AttributeMap { map: attrs, hash } }; @@ -604,18 +586,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node: hir::OwnerNode<'hir>, bodies: &SortedMap>, ) -> (Fingerprint, Fingerprint) { - let mut hcx = self.create_stable_hashing_context(); - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); - let hash_including_bodies = stable_hasher.finish(); - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); - let hash_without_bodies = stable_hasher.finish(); - (hash_including_bodies, hash_without_bodies) + self.tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let hash_including_bodies = stable_hasher.finish(); + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let hash_without_bodies = stable_hasher.finish(); + (hash_including_bodies, hash_without_bodies) + }) } /// This method allocates a new `HirId` for the given `NodeId` and stores it in @@ -703,12 +686,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, allow_internal_unstable: Option>, ) -> Span { - span.mark_with_reason( - allow_internal_unstable, - reason, - self.sess.edition(), - self.create_stable_hashing_context(), - ) + self.tcx.with_stable_hashing_context(|hcx| { + span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition(), hcx) + }) } /// Intercept all spans entering HIR. diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 064ed0cde9675..69ad623b7ea86 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" doctest = false [dependencies] +rustc_arena = { path = "../rustc_arena" } rustc_target = { path = "../rustc_target" } rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 5d1314ebb488d..a6d10f3adae9f 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -9,7 +9,7 @@ macro_rules! arena_types { // HIR types [] hir_krate: rustc_hir::Crate<'tcx>, [] arm: rustc_hir::Arm<'tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, Span), + [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, rustc_span::Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, [] block: rustc_hir::Block<'tcx>, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 9f32a7da159a2..0f9e6fa7b9895 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -18,6 +18,8 @@ extern crate rustc_macros; #[macro_use] extern crate rustc_data_structures; +extern crate self as rustc_hir; + mod arena; pub mod def; pub mod def_path_hash_map; @@ -41,3 +43,5 @@ pub use hir_id::*; pub use lang_items::{LangItem, LanguageItems}; pub use stable_hash_impls::HashStableContext; pub use target::{MethodKind, Target}; + +arena_types!(rustc_arena::declare_arena); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5b263aded9cdf..b7d1d6edfaa7b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -14,7 +14,6 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; -use rustc_hir::Crate; use rustc_lint::{EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_metadata::{encode_metadata, EncodedMetadata}; @@ -482,37 +481,6 @@ pub fn configure_and_expand( Ok(krate) } -fn lower_to_hir<'tcx>( - sess: &Session, - definitions: &mut Definitions, - cstore: &CrateStoreDyn, - resolutions: &ty::ResolverOutputs, - resolver: ty::ResolverAstLowering, - krate: Rc, - arena: &'tcx rustc_ast_lowering::Arena<'tcx>, -) -> &'tcx Crate<'tcx> { - // Lower AST to HIR. - let hir_crate = rustc_ast_lowering::lower_crate( - sess, - &krate, - definitions, - cstore, - resolutions, - resolver, - arena, - ); - - // Drop AST to free memory - sess.time("drop_ast", || std::mem::drop(krate)); - - // Discard hygiene data, which isn't required after lowering to HIR. - if !sess.opts.debugging_opts.keep_hygiene_data { - rustc_span::hygiene::clear_syntax_context_map(); - } - - hir_crate -} - // Returns all the paths that correspond to generated files. fn generated_output_paths( sess: &Session, @@ -777,6 +745,7 @@ pub fn prepare_outputs( pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; + providers.hir_crate = rustc_ast_lowering::lower_to_hir; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -823,7 +792,7 @@ impl<'tcx> QueryContext<'tcx> { pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc, - krate: Rc, + krate: Lrc, dep_graph: DepGraph, resolver: Rc>, outputs: OutputFilenames, @@ -831,29 +800,17 @@ pub fn create_global_ctxt<'tcx>( queries: &'tcx OnceCell>, global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, - hir_arena: &'tcx WorkerLocal>, + hir_arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to // incr. comp. yet. dep_graph.assert_ignored(); - let (mut definitions, cstore, resolver_outputs, resolver_for_lowering) = + let (definitions, cstore, resolver_outputs, resolver_for_lowering) = BoxedResolver::to_resolver_outputs(resolver); let sess = &compiler.session(); - - // Lower AST to HIR. - let krate = lower_to_hir( - sess, - &mut definitions, - &*cstore, - &resolver_outputs, - resolver_for_lowering, - krate, - hir_arena, - ); - let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); let codegen_backend = compiler.codegen_backend(); @@ -877,9 +834,11 @@ pub fn create_global_ctxt<'tcx>( sess, lint_store, arena, + hir_arena, definitions, cstore, resolver_outputs, + resolver_for_lowering, krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 136f0443fa0a3..8ffb1ad053994 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -72,13 +72,13 @@ pub struct Queries<'tcx> { queries: OnceCell>, arena: WorkerLocal>, - hir_arena: WorkerLocal>, + hir_arena: WorkerLocal>, dep_graph_future: Query>, parse: Query, crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, - expansion: Query<(Rc, Rc>, Lrc)>, + expansion: Query<(Lrc, Rc>, Lrc)>, dep_graph: Query, prepare_outputs: Query, global_ctxt: Query>, @@ -92,7 +92,7 @@ impl<'tcx> Queries<'tcx> { gcx: OnceCell::new(), queries: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), - hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()), + hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), crate_name: Default::default(), @@ -164,7 +164,7 @@ impl<'tcx> Queries<'tcx> { pub fn expansion( &self, - ) -> Result<&Query<(Rc, Rc>, Lrc)>> { + ) -> Result<&Query<(Lrc, Rc>, Lrc)>> { tracing::trace!("expansion"); self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); @@ -180,7 +180,7 @@ impl<'tcx> Queries<'tcx> { let krate = resolver.access(|resolver| { passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) })?; - Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) + Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index c1d8d76c975d8..27f67207209dd 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -34,7 +34,7 @@ use tracing::debug; /// Extract the `LintStore` from the query context. /// This function exists because we've erased `LintStore` as `dyn Any` in the context. -pub(crate) fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { +pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { let store: &dyn Any = &*tcx.lint_store; store.downcast_ref().unwrap() } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c1255ae5056ac..aaee0caa070e7 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -99,7 +99,7 @@ pub use builtin::SoftLints; pub use context::{CheckLintNameResult, FindLintError, LintStore}; pub use context::{EarlyContext, LateContext, LintContext}; pub use early::{check_ast_node, EarlyCheckNode}; -pub use late::check_crate; +pub use late::{check_crate, unerased_lint_store}; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId}; diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 8622a6207212c..427c9df028480 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -102,7 +102,6 @@ pub fn provide(providers: &mut Providers) { let hir = tcx.hir(); hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) }; - providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index abc639136d6d2..267395269e251 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -32,6 +32,12 @@ rustc_queries! { desc { "get the resolver outputs" } } + query resolver_for_lowering(_: ()) -> &'tcx Steal { + eval_always + no_hash + desc { "get the resolver for lowering" } + } + /// Return the span for a definition. /// Contrary to `def_span` below, this query returns the full absolute span of the definition. /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside @@ -46,7 +52,8 @@ rustc_queries! { /// This is because the `hir_crate` query gives you access to all other items. /// To avoid this fate, do not call `tcx.hir().krate()`; instead, /// prefer wrappers like `tcx.visit_all_items_in_krate()`. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { + query hir_crate(key: ()) -> Crate<'tcx> { + storage(ArenaCacheSelector<'tcx>) eval_always desc { "get the crate HIR" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 60329fc6eea40..a25523c236b5c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1049,6 +1049,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> { pub struct GlobalCtxt<'tcx> { pub arena: &'tcx WorkerLocal>, + pub hir_arena: &'tcx WorkerLocal>, interners: CtxtInterners<'tcx>, @@ -1078,8 +1079,8 @@ pub struct GlobalCtxt<'tcx> { /// Output of the resolver. pub(crate) untracked_resolutions: ty::ResolverOutputs, - - pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, + untracked_resolver_for_lowering: Steal, + pub untracked_crate: Steal>, /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by @@ -1237,10 +1238,12 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, lint_store: Lrc, arena: &'tcx WorkerLocal>, + hir_arena: &'tcx WorkerLocal>, definitions: Definitions, cstore: Box, untracked_resolutions: ty::ResolverOutputs, - krate: &'tcx hir::Crate<'tcx>, + untracked_resolver_for_lowering: ty::ResolverAstLowering, + krate: Lrc, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, @@ -1267,16 +1270,18 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, arena, + hir_arena, interners, dep_graph, definitions: RwLock::new(definitions), cstore, - untracked_resolutions, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, consts: common_consts, - untracked_crate: krate, + untracked_resolutions, + untracked_resolver_for_lowering: Steal::new(untracked_resolver_for_lowering), + untracked_crate: Steal::new(krate), on_disk_cache, queries, query_caches: query::QueryCaches::default(), @@ -2996,6 +3001,7 @@ fn ptr_eq(t: *const T, u: *const U) -> bool { pub fn provide(providers: &mut ty::query::Providers) { providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; + providers.resolver_for_lowering = |tcx, ()| &tcx.untracked_resolver_for_lowering; providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 89b9a80ee4dfa..843f6f9d70367 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -119,13 +119,13 @@ impl<'a> StableHashingContext<'a> { &mut self, hash_bodies: bool, owner: LocalDefId, - bodies: &'a SortedMap>, - f: impl FnOnce(&mut Self), + bodies: &SortedMap>, + f: impl FnOnce(&mut StableHashingContext<'_>), ) { - let prev = self.body_resolver; - self.body_resolver = BodyResolver::Traverse { hash_bodies, owner, bodies }; - f(self); - self.body_resolver = prev; + f(&mut StableHashingContext { + body_resolver: BodyResolver::Traverse { hash_bodies, owner, bodies }, + ..self.clone() + }); } #[inline] From fb060fb774c7e0f1e06dfb43c6173bc37079dfcd Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 2 Apr 2022 16:13:01 +0200 Subject: [PATCH 03/12] Remove useless branch. --- compiler/rustc_ast_lowering/src/lib.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ee978f39d2263..62682e837dcf3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -459,6 +459,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id: ast::NodeId, data: DefPathData, ) -> LocalDefId { + debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( self.opt_local_def_id(node_id).is_none(), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", @@ -469,13 +470,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let def_id = self.tcx.create_def(parent, data); - // Some things for which we allocate `LocalDefId`s don't correspond to - // anything in the AST, so they don't have a `NodeId`. For these cases - // we don't need a mapping from `NodeId` to `LocalDefId`. - if node_id != ast::DUMMY_NODE_ID { - debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); - self.resolver.node_id_to_def_id.insert(node_id, def_id); - } + debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); + self.resolver.node_id_to_def_id.insert(node_id, def_id); def_id } From 682f57656ed83c1017ad7288940280386f80efae Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 2 Apr 2022 16:13:20 +0200 Subject: [PATCH 04/12] Do not create a new NodeId when not used. --- compiler/rustc_ast_lowering/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 62682e837dcf3..4e90bad2c0a56 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -635,9 +635,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } + /// Generate a new `HirId` without a backing `NodeId`. fn next_id(&mut self) -> hir::HirId { - let node_id = self.next_node_id(); - self.lower_node_id(node_id) + let owner = self.current_hir_id_owner; + let local_id = self.item_local_id_counter; + assert_ne!(local_id, hir::ItemLocalId::new(0)); + self.item_local_id_counter.increment_by(1); + hir::HirId { owner, local_id } } #[instrument(level = "trace", skip(self))] From 15530a1c84b6ccc7f321ac855a76702677de2563 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Apr 2022 19:18:26 +0200 Subject: [PATCH 05/12] Create a forever red node and use it to force side effects. --- compiler/rustc_middle/src/query/mod.rs | 6 ----- compiler/rustc_middle/src/ty/context.rs | 20 ++++------------- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- compiler/rustc_query_impl/src/keys.rs | 11 ---------- .../rustc_query_system/src/dep_graph/graph.rs | 22 +++++++++++++++++-- 5 files changed, 26 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 267395269e251..cbc45526e89fb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -20,12 +20,6 @@ rustc_queries! { desc { "trigger a delay span bug" } } - /// Create a new definition within the incr. comp. engine. - query register_def(_: ty::RawLocalDefId) -> LocalDefId { - eval_always - desc { "register a DefId with the incr. comp. engine" } - } - query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { eval_always no_hash diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a25523c236b5c..2beac30426674 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -123,9 +123,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PlaceholderRegion = ty::PlaceholderRegion; } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] -pub struct RawLocalDefId(LocalDefId); - /// 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)] @@ -1477,23 +1474,15 @@ impl<'tcx> TyCtxt<'tcx> { let def_id = self.definitions.write().create_def(parent, data); // We need to ensure that these side effects are re-run by the incr. comp. engine. - // When the incr. comp. engine considers marking this query as green, eval_always requires - // we run the function to run. To invoke it, the parameter cannot be reconstructed from - // the DepNode, so the caller query is run. Luckily, we are inside the caller query, - // therefore the definition is properly created. - debug_assert!({ - use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; - self.is_eval_always(crate::dep_graph::DepKind::register_def) - && !>>::fingerprint_style() - .reconstructible() - }); + use rustc_query_system::dep_graph::DepNodeIndex; + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); // Any LocalDefId which is used within queries, either as key or result, either: // - has been created before the construction of the TyCtxt; - // - has been created by this call to `register_def`. + // - has been created by this call to `create_def`. // As a consequence, this LocalDefId is always re-created before it is needed by the incr. // comp. engine itself. - self.register_def(RawLocalDefId(def_id)) + def_id } pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { @@ -3033,5 +3022,4 @@ pub fn provide(providers: &mut ty::query::Providers) { // We want to check if the panic handler was defined in this crate tcx.lang_items().panic_impl().map_or(false, |did| did.is_local()) }; - providers.register_def = |_, raw_id| raw_id.0; } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e00cf3ff9bebc..3a795af2121d0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -72,8 +72,8 @@ pub use self::consts::{ pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData, - GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, RawLocalDefId, TyCtxt, - TypeckResults, UserType, UserTypeAnnotationIndex, + GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, + UserTypeAnnotationIndex, }; pub use self::instance::{Instance, InstanceDef}; pub use self::list::List; diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index c3fbba4456e1e..6fbafeb1d32b3 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -39,17 +39,6 @@ impl Key for () { } } -impl Key for ty::RawLocalDefId { - #[inline(always)] - fn query_crate_is_local(&self) -> bool { - true - } - - fn default_span(&self, _: TyCtxt<'_>) -> Span { - DUMMY_SP - } -} - impl<'tcx> Key for ty::InstanceDef<'tcx> { #[inline(always)] fn query_crate_is_local(&self) -> bool { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 0e1419f8a483a..d218e3b775314 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -43,6 +43,7 @@ rustc_index::newtype_index! { impl DepNodeIndex { pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0); + pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1); } impl std::convert::From for QueryInvocationId { @@ -124,6 +125,8 @@ impl DepGraph { record_stats, ); + let colors = DepNodeColorMap::new(prev_graph_node_count); + // Instantiate a dependy-less node only once for anonymous queries. let _green_node_index = current.intern_new_node( profiler, @@ -133,6 +136,18 @@ impl DepGraph { ); debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); + // Instantiate a dependy-less red node only once for anonymous queries. + let (_red_node_index, _prev_and_index) = current.intern_node( + profiler, + &prev_graph, + DepNode { kind: DepKind::NULL, hash: Fingerprint::ZERO.into() }, + smallvec![], + None, + false, + ); + debug_assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE); + debug_assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red)))); + DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, @@ -140,7 +155,7 @@ impl DepGraph { current, processed_side_effects: Default::default(), previous: prev_graph, - colors: DepNodeColorMap::new(prev_graph_node_count), + colors, debug_loaded_from_disk: Default::default(), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), @@ -965,6 +980,9 @@ impl CurrentDepGraph { let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64; let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); + let anon_id_seed = stable_hasher.finish(); + // We rely on the fact that `anon_id_seed` is not zero when creating static nodes. + debug_assert_ne!(anon_id_seed, Fingerprint::ZERO); #[cfg(debug_assertions)] let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { @@ -1000,7 +1018,7 @@ impl CurrentDepGraph { ) }), prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)), - anon_id_seed: stable_hasher.finish(), + anon_id_seed, #[cfg(debug_assertions)] forbidden_edge, total_read_count: AtomicU64::new(0), From 74be9458200febab1ca4bc8c0ef57f8ed1f096dc Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 2 May 2022 20:32:10 +0200 Subject: [PATCH 06/12] Expand comment in `with_hir_id_owner`. --- compiler/rustc_ast_lowering/src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4e90bad2c0a56..a5beb7b8e1ae1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -491,6 +491,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) } + /// Freshen the `LoweringContext` and ready it to lower a nested item. + /// The lowered item is registered into `self.children`. + /// + /// This function sets up `HirId` lowering infrastructure, + /// and stashes the shared mutable state to avoid pollution by the closure. #[instrument(level = "debug", skip(self, f))] fn with_hir_id_owner( &mut self, @@ -509,8 +514,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); let current_impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds); - // Do not reset `next_node_id` and `node_id_to_def_id` as we want to refer to the - // subdefinitions' nodes. + + // Do not reset `next_node_id` and `node_id_to_def_id`: + // we want `f` to be able to refer to the `LocalDefId`s that the caller created. + // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s. // Always allocate the first `HirId` for the owner itself. let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::new(0)); From 8fc3deb1b4edb6a91e8f6c2e08baa0323d67a84a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 2 May 2022 20:32:17 +0200 Subject: [PATCH 07/12] Remove `sess` field from LoweringContext. --- compiler/rustc_ast_lowering/src/asm.rs | 54 ++++++++++++++---------- compiler/rustc_ast_lowering/src/block.rs | 4 +- compiler/rustc_ast_lowering/src/expr.rs | 33 +++++++++------ compiler/rustc_ast_lowering/src/item.rs | 3 +- compiler/rustc_ast_lowering/src/lib.rs | 28 ++++++------ compiler/rustc_ast_lowering/src/path.rs | 4 +- 6 files changed, 69 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index aab9b90e4b7e5..0e395d7033586 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -24,10 +24,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> &'hir hir::InlineAsm<'hir> { // Rustdoc needs to support asm! from foreign architectures: don't try // lowering the register constraints in this case. - let asm_arch = if self.sess.opts.actually_rustdoc { None } else { self.sess.asm_arch }; - if asm_arch.is_none() && !self.sess.opts.actually_rustdoc { - struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target") - .emit(); + let asm_arch = + if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch }; + if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc { + struct_span_err!( + self.tcx.sess, + sp, + E0472, + "inline assembly is unsupported on this target" + ) + .emit(); } if let Some(asm_arch) = asm_arch { // Inline assembly is currently only stable for these architectures. @@ -40,9 +46,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | asm::InlineAsmArch::RiscV32 | asm::InlineAsmArch::RiscV64 ); - if !is_stable && !self.sess.features_untracked().asm_experimental_arch { + if !is_stable && !self.tcx.features().asm_experimental_arch { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::asm_experimental_arch, sp, "inline assembly is not stable yet on this architecture", @@ -52,17 +58,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) - && !self.sess.opts.actually_rustdoc + && !self.tcx.sess.opts.actually_rustdoc { - self.sess + self.tcx + .sess .struct_span_err(sp, "the `att_syntax` option is only supported on x86") .emit(); } - if asm.options.contains(InlineAsmOptions::MAY_UNWIND) - && !self.sess.features_untracked().asm_unwind - { + if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable", @@ -73,12 +78,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut clobber_abis = FxHashMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { Some((prev_name, prev_sp)) => { - let mut err = self.sess.struct_span_err( + let mut err = self.tcx.sess.struct_span_err( *abi_span, &format!("`{}` ABI specified multiple times", prev_name), ); @@ -86,7 +91,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Multiple different abi names may actually be the same ABI // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI - let source_map = self.sess.source_map(); + let source_map = self.tcx.sess.source_map(); if source_map.span_to_snippet(*prev_sp) != source_map.span_to_snippet(*abi_span) { @@ -101,7 +106,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } Err(&[]) => { - self.sess + self.tcx + .sess .struct_span_err( *abi_span, "`clobber_abi` is not supported on this target", @@ -109,8 +115,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .emit(); } Err(supported_abis) => { - let mut err = - self.sess.struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); + let mut err = self + .tcx + .sess + .struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); let mut abis = format!("`{}`", supported_abis[0]); for m in &supported_abis[1..] { let _ = write!(abis, ", `{}`", m); @@ -128,7 +136,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Lower operands to HIR. We use dummy register classes if an error // occurs during lowering because we still need to be able to produce a // valid HIR. - let sess = self.sess; + let sess = self.tcx.sess; let mut operands: Vec<_> = asm .operands .iter() @@ -184,9 +192,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } InlineAsmOperand::Const { ref anon_const } => { - if !self.sess.features_untracked().asm_const { + if !self.tcx.features().asm_const { feature_err( - &self.sess.parse_sess, + &sess.parse_sess, sym::asm_const, *op_sp, "const operands for inline assembly are unstable", @@ -198,9 +206,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } InlineAsmOperand::Sym { ref sym } => { - if !self.sess.features_untracked().asm_sym { + if !self.tcx.features().asm_sym { feature_err( - &self.sess.parse_sess, + &sess.parse_sess, sym::asm_sym, *op_sp, "sym operands for inline assembly are unstable", diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 3a7e0a70585f1..9444fffc331c7 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -159,9 +159,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)), }); - if !self.sess.features_untracked().let_else { + if !self.tcx.features().let_else { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::let_else, local.span, "`let...else` statements are unstable", diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3babe73030a45..9e02e7ed3b9cf 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -46,7 +46,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(e.id); return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; } else { - self.sess + self.tcx.sess .struct_span_err( e.span, "#[rustc_box] requires precisely one argument \ @@ -207,8 +207,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims) } ExprKind::Underscore => { - self.sess - .struct_span_err( + self.tcx + .sess.struct_span_err( e.span, "in expressions, `_` can only be used on the left-hand side of an assignment", ) @@ -245,7 +245,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Rest(sp) => { - self.sess + self.tcx + .sess .struct_span_err(*sp, "base expression required after `..`") .span_label(*sp, "add a base expression here") .emit(); @@ -474,7 +475,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } else { let try_span = this.mark_span_with_reason( DesugaringKind::TryBlock, - this.sess.source_map().end_point(body.span), + this.tcx.sess.source_map().end_point(body.span), this.allow_try_trait.clone(), ); @@ -653,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { let mut err = struct_span_err!( - self.sess, + self.tcx.sess, dot_await_span, E0728, "`await` is only allowed inside `async` functions and blocks" @@ -878,7 +879,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Gen) => { if decl.inputs.len() > 1 { struct_span_err!( - self.sess, + self.tcx.sess, fn_decl_span, E0628, "too many parameters for a generator (expected 0 or 1 parameters)" @@ -892,8 +893,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } None => { if movability == Movability::Static { - struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static") - .emit(); + struct_span_err!( + self.tcx.sess, + fn_decl_span, + E0697, + "closures cannot be static" + ) + .emit(); } None } @@ -916,7 +922,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { struct_span_err!( - this.sess, + this.tcx.sess, fn_decl_span, E0708, "`async` non-`move` closures with parameters are not currently supported", @@ -1163,7 +1169,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let fields_omitted = match &se.rest { StructRest::Base(e) => { - self.sess + self.tcx + .sess .struct_span_err( e.span, "functional record updates are not allowed in destructuring \ @@ -1371,7 +1378,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::GeneratorKind::Gen) => {} Some(hir::GeneratorKind::Async(_)) => { struct_span_err!( - self.sess, + self.tcx.sess, span, E0727, "`async` generators are not yet supported" @@ -1516,7 +1523,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, self.allow_try_trait.clone(), ); - let try_span = self.sess.source_map().end_point(span); + let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3acca74a4cd92..ec9f47ce590d9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -58,7 +58,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { let mut lctx = LoweringContext { // Pseudo-globals. tcx: self.tcx, - sess: &self.tcx.sess, resolver: self.resolver, arena: self.tcx.hir_arena, @@ -1268,7 +1267,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn error_on_invalid_abi(&self, abi: StrLit) { - struct_span_err!(self.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol) + struct_span_err!(self.tcx.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol) .span_label(abi.span, "invalid ABI") .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) .emit(); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a5beb7b8e1ae1..2dcbd0782ef72 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -49,7 +49,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, Handler}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -58,7 +58,6 @@ use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::feature_err; -use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -83,7 +82,6 @@ mod path; struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, - sess: &'hir Session, resolver: &'a mut ResolverAstLowering, /// Used to allocate HIR nodes. @@ -681,8 +679,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_import_res(id).present_items() } - fn diagnostic(&self) -> &rustc_errors::Handler { - self.sess.diagnostic() + fn diagnostic(&self) -> &Handler { + self.tcx.sess.diagnostic() } /// Reuses the span but adds information like the kind of the desugaring and features that are @@ -694,14 +692,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { allow_internal_unstable: Option>, ) -> Span { self.tcx.with_stable_hashing_context(|hcx| { - span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition(), hcx) + span.mark_with_reason(allow_internal_unstable, reason, self.tcx.sess.edition(), hcx) }) } /// Intercept all spans entering HIR. /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { - if self.sess.opts.debugging_opts.incremental_relative_spans { + if self.tcx.sess.opts.debugging_opts.incremental_relative_spans { span.with_parent(Some(self.current_hir_id_owner)) } else { // Do not make spans relative when not using incremental compilation. @@ -1048,7 +1046,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) { - let mut err = self.sess.struct_span_err( + let mut err = self.tcx.sess.struct_span_err( data.span, "parenthesized generic arguments cannot be used in associated type constraints", ); @@ -1093,7 +1091,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { match ty.kind { - TyKind::Infer if self.sess.features_untracked().generic_arg_infer => { + TyKind::Infer if self.tcx.features().generic_arg_infer => { return GenericArg::Infer(hir::InferArg { hir_id: self.lower_node_id(ty.id), span: self.lower_span(ty.span), @@ -1190,7 +1188,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.next_node_id() }; - let span = self.sess.source_map().next_point(t.span.shrink_to_lo()); + let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo()); Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); let lifetime = self.lower_lifetime(®ion); @@ -1294,7 +1292,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::Disallowed(position) => { let mut err = struct_span_err!( - self.sess, + self.tcx.sess, t.span, E0562, "`impl Trait` only allowed in function and inherent method return types, not in {}", @@ -1307,7 +1305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::CVarArgs => { - self.sess.delay_span_bug( + self.tcx.sess.delay_span_bug( t.span, "`TyKind::CVarArgs` should have been handled elsewhere", ); @@ -1912,7 +1910,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir_id, name, span: self.lower_span(param.span()), - pure_wrt_drop: self.sess.contains_name(¶m.attrs, sym::may_dangle), + pure_wrt_drop: self.tcx.sess.contains_name(¶m.attrs, sym::may_dangle), kind, colon_span: param.colon_span.map(|s| self.lower_span(s)), } @@ -2054,11 +2052,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { match c.value.kind { ExprKind::Underscore => { - if self.sess.features_untracked().generic_arg_infer { + if self.tcx.features().generic_arg_infer { hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span) } else { feature_err( - &self.sess.parse_sess, + &self.tcx.sess.parse_sess, sym::generic_arg_infer, c.value.span, "using `_` for array lengths is unstable", diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 52ba5daf01410..393be3b454c37 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -133,7 +133,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We should've returned in the for loop above. - self.sess.diagnostic().span_bug( + self.diagnostic().span_bug( p.span, &format!( "lower_qpath: no final extension segment in {}..{}", @@ -193,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Err => { - let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg); + let mut err = struct_span_err!(self.tcx.sess, data.span, E0214, "{}", msg); err.span_label(data.span, "only `Fn` traits may use parentheses"); // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` if !data.inputs.is_empty() { From c168fba268082c1a9203550ac72d12ece143814f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 3 May 2022 22:01:01 +0200 Subject: [PATCH 08/12] Comment untracked_crate. --- compiler/rustc_middle/src/ty/context.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2beac30426674..a750bb8abd02d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1077,6 +1077,8 @@ pub struct GlobalCtxt<'tcx> { /// Output of the resolver. pub(crate) untracked_resolutions: ty::ResolverOutputs, untracked_resolver_for_lowering: Steal, + /// The entire crate as AST. This field serves as the input for the hir_crate query, + /// which lowers it from AST to HIR. It must not be read or used by anything else. pub untracked_crate: Steal>, /// This provides access to the incremental compilation on-disk cache for query results. From e912c8dfe0f74f41c9b3dae1a4e1900f3dd9d0e6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 3 May 2022 22:04:49 +0200 Subject: [PATCH 09/12] Use a dedicated DepKind for the forever-red node. --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 3 +++ compiler/rustc_middle/src/dep_graph/mod.rs | 1 + compiler/rustc_query_impl/src/plumbing.rs | 11 +++++++++++ compiler/rustc_query_system/src/dep_graph/graph.rs | 10 ++++------ compiler/rustc_query_system/src/dep_graph/mod.rs | 4 ++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 555baae35f506..2d095438fc4e9 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -183,6 +183,9 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, + // We use this to create a forever-red node. + [] Red, + [anon] TraitSelect, // WARNING: if `Symbol` is changed, make sure you update `make_compile_codegen_unit` below. diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 5f3f1a3bc6c3a..c8b3b52b0fb2b 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -23,6 +23,7 @@ pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; + const RED: Self = DepKind::Red; fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}(", node.kind)?; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d0fef364eafd8..333dc5aa668b0 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -377,6 +377,17 @@ macro_rules! define_queries { } } + // We use this for the forever-red node. + pub fn Red() -> DepKindStruct { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + try_load_from_on_disk_cache: None, + } + } + pub fn TraitSelect() -> DepKindStruct { DepKindStruct { is_anon: true, diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index d218e3b775314..a1df192cc4528 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -134,19 +134,19 @@ impl DepGraph { smallvec![], Fingerprint::ZERO, ); - debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); + assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); // Instantiate a dependy-less red node only once for anonymous queries. let (_red_node_index, _prev_and_index) = current.intern_node( profiler, &prev_graph, - DepNode { kind: DepKind::NULL, hash: Fingerprint::ZERO.into() }, + DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() }, smallvec![], None, false, ); - debug_assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE); - debug_assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red)))); + assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE); + assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red)))); DepGraph { data: Some(Lrc::new(DepGraphData { @@ -981,8 +981,6 @@ impl CurrentDepGraph { let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); let anon_id_seed = stable_hasher.finish(); - // We rely on the fact that `anon_id_seed` is not zero when creating static nodes. - debug_assert_ne!(anon_id_seed, Fingerprint::ZERO); #[cfg(debug_assertions)] let forbidden_edge = match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 345ada263e4d2..342d95ca490ea 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -85,8 +85,12 @@ impl FingerprintStyle { /// Describe the different families of dependency nodes. pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { + /// DepKind to use when incr. comp. is turned off. const NULL: Self; + /// DepKind to use to create the initial forever-red node. + const RED: Self; + /// Implementation of `std::fmt::Debug` for `DepNode`. fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; From e475a69fa8d5da30be90179b883704d0ba74c150 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 3 May 2022 22:14:07 +0200 Subject: [PATCH 10/12] Reword create_def comment. --- compiler/rustc_middle/src/ty/context.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a750bb8abd02d..38e4095997c97 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1470,21 +1470,28 @@ impl<'tcx> TyCtxt<'tcx> { /// Create a new definition within the incr. comp. engine. pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) -> LocalDefId { - // The following call has the side effect of modifying the tables inside `definitions`. - // These very tables are relied on by the incr. comp. engine to decode DepNodes and to - // decode the on-disk cache. - let def_id = self.definitions.write().create_def(parent, data); - + // This function modifies `self.definitions` using a side-effect. // We need to ensure that these side effects are re-run by the incr. comp. engine. + // Depending on the forever-red node will tell the graph that the calling query + // needs to be re-evaluated. use rustc_query_system::dep_graph::DepNodeIndex; self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + // The following call has the side effect of modifying the tables inside `definitions`. + // These very tables are relied on by the incr. comp. engine to decode DepNodes and to + // decode the on-disk cache. + // // Any LocalDefId which is used within queries, either as key or result, either: // - has been created before the construction of the TyCtxt; // - has been created by this call to `create_def`. // As a consequence, this LocalDefId is always re-created before it is needed by the incr. // comp. engine itself. - def_id + // + // This call also writes to the value of `source_span` and `expn_that_defined` queries. + // This is fine because: + // - those queries are `eval_always` so we won't miss their result changing; + // - this write will have happened before these queries are called. + self.definitions.write().create_def(parent, data) } pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { From 2c3b4ff995c3595df22baaa1da2514946aed56e3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 3 May 2022 22:14:44 +0200 Subject: [PATCH 11/12] Remove dead code. --- compiler/rustc_middle/src/ty/context.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 38e4095997c97..a594dab2e20a3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1561,21 +1561,6 @@ impl<'tcx> TyCtxt<'tcx> { f(hcx) } - #[inline(always)] - pub fn with_no_span_stable_hashing_context( - self, - f: impl FnOnce(StableHashingContext<'_>) -> R, - ) -> R { - let definitions = self.definitions_untracked(); - let hcx = StableHashingContext::ignore_spans( - self.sess, - &*definitions, - &*self.cstore, - &self.untracked_resolutions.source_span, - ); - f(hcx) - } - pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult { self.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder)) } From 32a30cad0375e61eeac483f811413a9a26102ebf Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 2 Jun 2022 20:08:38 +0200 Subject: [PATCH 12/12] Use DefIdTree instead of re-implementing it. --- compiler/rustc_ast_lowering/src/item.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ec9f47ce590d9..ef9761eae8e11 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -13,7 +13,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -133,12 +133,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = { - let parent = self.tcx.hir().def_key(def_id).parent; - let local_def_index = parent.unwrap(); - LocalDefId { local_def_index } - }; - + let parent_id = self.tcx.local_parent(def_id); let parent_hir = self.lower_node(parent_id).unwrap(); self.with_lctx(item.id, |lctx| { // Evaluate with the lifetimes in `params` in-scope.