diff options
Diffstat (limited to 'compiler/rustc_query_system/src')
| -rw-r--r-- | compiler/rustc_query_system/src/dep_graph/dep_node.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/dep_graph/graph.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/dep_graph/mod.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/ich/hcx.rs | 212 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/ich/impls_hir.rs | 155 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/ich/impls_syntax.rs | 146 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/ich/mod.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_query_system/src/query/config.rs | 11 |
9 files changed, 550 insertions, 22 deletions
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 46dc0c720ce..dd500015374 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -43,10 +43,10 @@ //! lost during fingerprint computation. use super::{DepContext, DepKind}; +use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - use std::fmt; use std::hash::Hash; @@ -119,7 +119,7 @@ pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized { impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T where - T: HashStable<Ctxt::StableHashingContext> + fmt::Debug, + T: for<'a> HashStable<StableHashingContext<'a>> + fmt::Debug, { #[inline] default fn can_reconstruct_query_key() -> bool { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 23a43771842..114d12fb90b 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1,3 +1,4 @@ +use parking_lot::Mutex; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef}; @@ -7,8 +8,6 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; use rustc_index::vec::IndexVec; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; - -use parking_lot::Mutex; use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use std::fmt::Debug; @@ -19,6 +18,7 @@ use std::sync::atomic::Ordering::Relaxed; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; +use crate::ich::StableHashingContext; use crate::query::{QueryContext, QuerySideEffects}; #[cfg(debug_assertions)] @@ -96,9 +96,9 @@ struct DepGraphData<K: DepKind> { dep_node_debug: Lock<FxHashMap<DepNode<K>, String>>, } -pub fn hash_result<HashCtxt, R>(hcx: &mut HashCtxt, result: &R) -> Option<Fingerprint> +pub fn hash_result<R>(hcx: &mut StableHashingContext<'_>, result: &R) -> Option<Fingerprint> where - R: HashStable<HashCtxt>, + R: for<'a> HashStable<StableHashingContext<'a>>, { let mut stable_hasher = StableHasher::new(); result.hash_stable(hcx, &mut stable_hasher); @@ -215,7 +215,7 @@ impl<K: DepKind> DepGraph<K> { cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, - hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>, + hash_result: fn(&mut StableHashingContext<'_>, &R) -> Option<Fingerprint>, ) -> (R, DepNodeIndex) { if self.is_fully_enabled() { self.with_task_impl(key, cx, arg, task, hash_result) @@ -234,7 +234,7 @@ impl<K: DepKind> DepGraph<K> { cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, - hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>, + hash_result: fn(&mut StableHashingContext<'_>, &R) -> Option<Fingerprint>, ) -> (R, DepNodeIndex) { // This function is only called when the graph is enabled. let data = self.data.as_ref().unwrap(); diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index b5be1192ce7..2afef210254 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -9,6 +9,7 @@ pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, Wor pub use query::DepGraphQuery; pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; +use crate::ich::StableHashingContext; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; use rustc_serialize::{opaque::FileEncoder, Encodable}; @@ -19,10 +20,9 @@ use std::hash::Hash; pub trait DepContext: Copy { type DepKind: self::DepKind; - type StableHashingContext; /// Create a hashing context for hashing new results. - fn create_stable_hashing_context(&self) -> Self::StableHashingContext; + fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; /// Access the DepGraph. fn dep_graph(&self) -> &DepGraph<Self::DepKind>; @@ -36,18 +36,13 @@ pub trait DepContext: Copy { pub trait HasDepContext: Copy { type DepKind: self::DepKind; - type StableHashingContext; - type DepContext: self::DepContext< - DepKind = Self::DepKind, - StableHashingContext = Self::StableHashingContext, - >; + type DepContext: self::DepContext<DepKind = Self::DepKind>; fn dep_context(&self) -> &Self::DepContext; } impl<T: DepContext> HasDepContext for T { type DepKind = T::DepKind; - type StableHashingContext = T::StableHashingContext; type DepContext = Self; fn dep_context(&self) -> &Self::DepContext { diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs new file mode 100644 index 00000000000..f2e935c59fc --- /dev/null +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -0,0 +1,212 @@ +use crate::ich; +use rustc_ast as ast; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::Lrc; +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::definitions::{DefPathHash, Definitions}; +use rustc_session::cstore::CrateStore; +use rustc_session::Session; +use rustc_span::source_map::SourceMap; +use rustc_span::symbol::Symbol; +use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData}; + +fn compute_ignored_attr_names() -> FxHashSet<Symbol> { + debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); + ich::IGNORED_ATTRIBUTES.iter().copied().collect() +} + +/// This is the context state available during incr. comp. hashing. It contains +/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., +/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various +/// things (e.g., each `DefId`/`DefPath` is only hashed once). +#[derive(Clone)] +pub struct StableHashingContext<'a> { + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + pub(super) body_resolver: BodyResolver<'a>, + hash_spans: bool, + hash_bodies: bool, + pub(super) node_id_hashing_mode: NodeIdHashingMode, + + // Very often, we are hashing something that does not need the + // `CachingSourceMapView`, so we initialize it lazily. + raw_source_map: &'a SourceMap, + caching_source_map: Option<CachingSourceMapView<'a>>, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +pub enum NodeIdHashingMode { + Ignore, + HashDefPath, +} + +/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. +/// We could also just store a plain reference to the `hir::Crate` but we want +/// to avoid that the crate is used to get untracked access to all of the HIR. +#[derive(Clone, Copy)] +pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>); + +impl<'tcx> BodyResolver<'tcx> { + /// Returns a reference to the `hir::Body` with the given `BodyId`. + /// **Does not do any tracking**; use carefully. + pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> { + self.0.body(id) + } +} + +impl<'a> StableHashingContext<'a> { + /// The `krate` here is only used for mapping `BodyId`s to `Body`s. + /// Don't use it for anything else or you'll run the risk of + /// leaking data out of the tracking system. + #[inline] + fn new_with_or_without_spans( + sess: &'a Session, + krate: &'a hir::Crate<'a>, + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + always_ignore_spans: bool, + ) -> Self { + let hash_spans_initial = + !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; + + StableHashingContext { + body_resolver: BodyResolver(krate), + definitions, + cstore, + caching_source_map: None, + raw_source_map: sess.source_map(), + hash_spans: hash_spans_initial, + hash_bodies: true, + node_id_hashing_mode: NodeIdHashingMode::HashDefPath, + } + } + + #[inline] + pub fn new( + sess: &'a Session, + krate: &'a hir::Crate<'a>, + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + ) -> Self { + Self::new_with_or_without_spans( + sess, + krate, + definitions, + cstore, + /*always_ignore_spans=*/ false, + ) + } + + #[inline] + pub fn ignore_spans( + sess: &'a Session, + krate: &'a hir::Crate<'a>, + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + ) -> Self { + let always_ignore_spans = true; + Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans) + } + + #[inline] + pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self, hash_bodies: bool, f: F) { + let prev_hash_bodies = self.hash_bodies; + self.hash_bodies = hash_bodies; + f(self); + self.hash_bodies = prev_hash_bodies; + } + + #[inline] + pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) { + let prev_hash_spans = self.hash_spans; + self.hash_spans = hash_spans; + f(self); + self.hash_spans = prev_hash_spans; + } + + #[inline] + pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>( + &mut self, + mode: NodeIdHashingMode, + f: F, + ) { + let prev = self.node_id_hashing_mode; + self.node_id_hashing_mode = mode; + f(self); + self.node_id_hashing_mode = prev; + } + + #[inline] + pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + if let Some(def_id) = def_id.as_local() { + self.local_def_path_hash(def_id) + } else { + self.cstore.def_path_hash(def_id) + } + } + + #[inline] + pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { + self.definitions.def_path_hash(def_id) + } + + #[inline] + pub fn hash_bodies(&self) -> bool { + self.hash_bodies + } + + #[inline] + pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { + match self.caching_source_map { + Some(ref mut sm) => sm, + ref mut none => { + *none = Some(CachingSourceMapView::new(self.raw_source_map)); + none.as_mut().unwrap() + } + } + } + + #[inline] + pub fn is_ignored_attr(&self, name: Symbol) -> bool { + thread_local! { + static IGNORED_ATTRIBUTES: FxHashSet<Symbol> = compute_ignored_attr_names(); + } + IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId { + #[inline] + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + panic!("Node IDs should not appear in incremental state"); + } +} + +impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { + #[inline] + fn hash_spans(&self) -> bool { + self.hash_spans + } + + #[inline] + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + self.def_path_hash(def_id) + } + + #[inline] + fn def_span(&self, def_id: LocalDefId) -> Span { + self.definitions.def_span(def_id) + } + + #[inline] + fn span_data_to_lines_and_cols( + &mut self, + span: &SpanData, + ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> { + self.source_map().span_data_to_lines_and_cols(span) + } +} + +impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs new file mode 100644 index 00000000000..04eb263a977 --- /dev/null +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -0,0 +1,155 @@ +//! This module contains `HashStable` implementations for various HIR data +//! types in no particular order. + +use crate::ich::{NodeIdHashingMode, StableHashingContext}; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_hir as hir; +use rustc_hir::definitions::DefPathHash; +use smallvec::SmallVec; +use std::mem; + +impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { + #[inline] + fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) { + let hcx = self; + match hcx.node_id_hashing_mode { + NodeIdHashingMode::Ignore => { + // Don't do anything. + } + NodeIdHashingMode::HashDefPath => { + let hir::HirId { owner, local_id } = hir_id; + + hcx.local_def_path_hash(owner).hash_stable(hcx, hasher); + local_id.hash_stable(hcx, hasher); + } + } + } + + #[inline] + fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { + let hcx = self; + if hcx.hash_bodies() { + hcx.body_resolver.body(id).hash_stable(hcx, hasher); + } + } + + #[inline] + fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) { + let hcx = self; + + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + id.hash_stable(hcx, hasher); + }) + } + + #[inline] + fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { + let hcx = self; + let hir::Mod { inner: ref inner_span, ref item_ids } = *module; + + inner_span.hash_stable(hcx, hasher); + + // Combining the `DefPathHash`s directly is faster than feeding them + // into the hasher. Because we use a commutative combine, we also don't + // have to sort the array. + let item_ids_hash = item_ids + .iter() + .map(|id| { + let def_path_hash = id.to_stable_hash_key(hcx); + def_path_hash.0 + }) + .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b)); + + item_ids.len().hash_stable(hcx, hasher); + item_ids_hash.hash_stable(hcx, hasher); + } + + fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) { + self.while_hashing_hir_bodies(true, |hcx| { + let hir::Expr { hir_id: _, ref span, ref kind } = *expr; + + span.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + }) + } + + fn hash_hir_ty(&mut self, ty: &hir::Ty<'_>, hasher: &mut StableHasher) { + self.while_hashing_hir_bodies(true, |hcx| { + let hir::Ty { hir_id: _, ref kind, ref span } = *ty; + + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }) + } + + fn hash_hir_visibility_kind( + &mut self, + vis: &hir::VisibilityKind<'_>, + hasher: &mut StableHasher, + ) { + let hcx = self; + mem::discriminant(vis).hash_stable(hcx, hasher); + match *vis { + hir::VisibilityKind::Public | hir::VisibilityKind::Inherited => { + // No fields to hash. + } + hir::VisibilityKind::Crate(sugar) => { + sugar.hash_stable(hcx, hasher); + } + hir::VisibilityKind::Restricted { ref path, hir_id } => { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + hir_id.hash_stable(hcx, hasher); + }); + path.hash_stable(hcx, hasher); + } + } + } + + #[inline] + fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) { + let prev_hash_node_ids = self.node_id_hashing_mode; + self.node_id_hashing_mode = NodeIdHashingMode::Ignore; + + f(self); + + self.node_id_hashing_mode = prev_hash_node_ids; + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for hir::Body<'_> { + #[inline] + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let hir::Body { params, value, generator_kind } = self; + + hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { + params.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + generator_kind.hash_stable(hcx, hasher); + }); + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let hir::TraitCandidate { def_id, import_ids } = self; + + def_id.hash_stable(hcx, hasher); + import_ids.hash_stable(hcx, hasher); + }); + } +} + +impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate { + type KeyType = (DefPathHash, SmallVec<[DefPathHash; 1]>); + + fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType { + let hir::TraitCandidate { def_id, import_ids } = self; + + ( + hcx.def_path_hash(*def_id), + import_ids.iter().map(|def_id| hcx.local_def_path_hash(*def_id)).collect(), + ) + } +} diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs new file mode 100644 index 00000000000..acf2990b643 --- /dev/null +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -0,0 +1,146 @@ +//! This module contains `HashStable` implementations for various data types +//! from `rustc_ast` in no particular order. + +use crate::ich::StableHashingContext; + +use rustc_ast as ast; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_span::{BytePos, NormalizedPos, SourceFile}; +use std::assert_matches::assert_matches; + +use smallvec::SmallVec; + +impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {} + +impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + if self.is_empty() { + self.len().hash_stable(hcx, hasher); + return; + } + + // Some attributes are always ignored during hashing. + let filtered: SmallVec<[&ast::Attribute; 8]> = self + .iter() + .filter(|attr| { + !attr.is_doc_comment() + && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)) + }) + .collect(); + + filtered.len().hash_stable(hcx, hasher); + for attr in filtered { + attr.hash_stable(hcx, hasher); + } + } +} + +impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> { + fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) { + // Make sure that these have been filtered out. + debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name))); + debug_assert!(!attr.is_doc_comment()); + + let ast::Attribute { kind, id: _, style, span } = attr; + if let ast::AttrKind::Normal(item, tokens) = kind { + item.hash_stable(self, hasher); + style.hash_stable(self, hasher); + span.hash_stable(self, hasher); + assert_matches!( + tokens.as_ref(), + None, + "Tokens should have been removed during lowering!" + ); + } else { + unreachable!(); + } + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for SourceFile { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let SourceFile { + name: _, // We hash the smaller name_hash instead of this + name_hash, + cnum, + // Do not hash the source as it is not encoded + src: _, + ref src_hash, + external_src: _, + start_pos, + end_pos: _, + ref lines, + ref multibyte_chars, + ref non_narrow_chars, + ref normalized_pos, + } = *self; + + (name_hash as u64).hash_stable(hcx, hasher); + + src_hash.hash_stable(hcx, hasher); + + // We only hash the relative position within this source_file + lines.len().hash_stable(hcx, hasher); + for &line in lines.iter() { + stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); + } + + // We only hash the relative position within this source_file + multibyte_chars.len().hash_stable(hcx, hasher); + for &char_pos in multibyte_chars.iter() { + stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); + } + + non_narrow_chars.len().hash_stable(hcx, hasher); + for &char_pos in non_narrow_chars.iter() { + stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher); + } + + normalized_pos.len().hash_stable(hcx, hasher); + for &char_pos in normalized_pos.iter() { + stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); + } + + cnum.hash_stable(hcx, hasher); + } +} + +fn stable_byte_pos(pos: BytePos, source_file_start: BytePos) -> u32 { + pos.0 - source_file_start.0 +} + +fn stable_multibyte_char(mbc: rustc_span::MultiByteChar, source_file_start: BytePos) -> (u32, u32) { + let rustc_span::MultiByteChar { pos, bytes } = mbc; + + (pos.0 - source_file_start.0, bytes as u32) +} + +fn stable_non_narrow_char( + swc: rustc_span::NonNarrowChar, + source_file_start: BytePos, +) -> (u32, u32) { + let pos = swc.pos(); + let width = swc.width(); + + (pos.0 - source_file_start.0, width as u32) +} + +fn stable_normalized_pos(np: NormalizedPos, source_file_start: BytePos) -> (u32, u32) { + let NormalizedPos { pos, diff } = np; + + (pos.0 - source_file_start.0, diff) +} + +impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features { + fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + // Unfortunately we cannot exhaustively list fields here, since the + // struct is macro generated. + self.declared_lang_features.hash_stable(hcx, hasher); + self.declared_lib_features.hash_stable(hcx, hasher); + + self.walk_feature_fields(|feature_name, value| { + feature_name.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); + } +} diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs new file mode 100644 index 00000000000..54416902e5f --- /dev/null +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -0,0 +1,19 @@ +//! ICH - Incremental Compilation Hash + +pub use self::hcx::{NodeIdHashingMode, StableHashingContext}; +use rustc_span::symbol::{sym, Symbol}; + +mod hcx; +mod impls_hir; +mod impls_syntax; + +pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ + sym::cfg, + sym::rustc_if_this_changed, + sym::rustc_then_this_would_need, + sym::rustc_dirty, + sym::rustc_clean, + sym::rustc_partition_reused, + sym::rustc_partition_codegened, + sym::rustc_expected_cgu_reuse, +]; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index c205f0fb531..bc23de069b0 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(assert_matches)] #![feature(bool_to_option)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] @@ -14,4 +15,5 @@ extern crate rustc_macros; pub mod cache; pub mod dep_graph; +pub mod ich; pub mod query; diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index d1e527dff98..76a165ed8e6 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -2,6 +2,7 @@ use crate::dep_graph::DepNode; use crate::dep_graph::SerializedDepNodeIndex; +use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::{QueryCacheStore, QueryContext, QueryState}; @@ -23,7 +24,7 @@ pub(crate) struct QueryVtable<CTX: QueryContext, K, V> { pub dep_kind: CTX::DepKind, pub eval_always: bool, - pub hash_result: fn(&mut CTX::StableHashingContext, &V) -> Option<Fingerprint>, + pub hash_result: fn(&mut StableHashingContext<'_>, &V) -> Option<Fingerprint>, pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V, pub cache_on_disk: fn(CTX, &K, Option<&V>) -> bool, pub try_load_from_disk: fn(CTX, SerializedDepNodeIndex) -> Option<V>, @@ -39,7 +40,7 @@ impl<CTX: QueryContext, K, V> QueryVtable<CTX, K, V> { pub(crate) fn hash_result( &self, - hcx: &mut CTX::StableHashingContext, + hcx: &mut StableHashingContext<'_>, value: &V, ) -> Option<Fingerprint> { (self.hash_result)(hcx, value) @@ -74,10 +75,8 @@ pub trait QueryAccessors<CTX: QueryContext>: QueryConfig { // Don't use this method to compute query results, instead use the methods on TyCtxt fn compute_fn(tcx: CTX, key: &Self::Key) -> fn(CTX::DepContext, Self::Key) -> Self::Value; - fn hash_result( - hcx: &mut CTX::StableHashingContext, - result: &Self::Value, - ) -> Option<Fingerprint>; + fn hash_result(hcx: &mut StableHashingContext<'_>, result: &Self::Value) + -> Option<Fingerprint>; fn handle_cycle_error(tcx: CTX, diag: DiagnosticBuilder<'_>) -> Self::Value; } |
