summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_query_system/src/ich
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /compiler/rustc_query_system/src/ich
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_query_system/src/ich')
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs223
-rw-r--r--compiler/rustc_query_system/src/ich/impls_hir.rs42
-rw-r--r--compiler/rustc_query_system/src/ich/impls_syntax.rs150
-rw-r--r--compiler/rustc_query_system/src/ich/mod.rs19
4 files changed, 434 insertions, 0 deletions
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 000000000..217fac341
--- /dev/null
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -0,0 +1,223 @@
+use crate::ich;
+
+use rustc_ast as ast;
+use rustc_data_structures::sorted_map::SortedMap;
+use rustc_data_structures::stable_hasher::{HashStable, HashingControls, 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_index::vec::IndexVec;
+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};
+
+/// 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,
+ source_span: &'a IndexVec<LocalDefId, Span>,
+ // The value of `-Z incremental-ignore-spans`.
+ // This field should only be used by `unstable_opts_incremental_ignore_span`
+ incremental_ignore_spans: bool,
+ pub(super) body_resolver: BodyResolver<'a>,
+ // 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>>,
+ pub(super) hashing_controls: HashingControls,
+}
+
+/// 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) enum BodyResolver<'tcx> {
+ Forbidden,
+ Traverse {
+ hash_bodies: bool,
+ owner: LocalDefId,
+ bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>,
+ },
+}
+
+impl<'a> StableHashingContext<'a> {
+ #[inline]
+ fn new_with_or_without_spans(
+ sess: &'a Session,
+ definitions: &'a Definitions,
+ cstore: &'a dyn CrateStore,
+ source_span: &'a IndexVec<LocalDefId, Span>,
+ always_ignore_spans: bool,
+ ) -> Self {
+ let hash_spans_initial =
+ !always_ignore_spans && !sess.opts.unstable_opts.incremental_ignore_spans;
+
+ StableHashingContext {
+ body_resolver: BodyResolver::Forbidden,
+ definitions,
+ cstore,
+ source_span,
+ incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
+ caching_source_map: None,
+ raw_source_map: sess.source_map(),
+ hashing_controls: HashingControls { hash_spans: hash_spans_initial },
+ }
+ }
+
+ #[inline]
+ pub fn new(
+ sess: &'a Session,
+ definitions: &'a Definitions,
+ cstore: &'a dyn CrateStore,
+ source_span: &'a IndexVec<LocalDefId, Span>,
+ ) -> Self {
+ Self::new_with_or_without_spans(
+ sess,
+ definitions,
+ cstore,
+ source_span,
+ /*always_ignore_spans=*/ false,
+ )
+ }
+
+ #[inline]
+ pub fn ignore_spans(
+ sess: &'a Session,
+ definitions: &'a Definitions,
+ cstore: &'a dyn CrateStore,
+ source_span: &'a IndexVec<LocalDefId, Span>,
+ ) -> Self {
+ let always_ignore_spans = true;
+ Self::new_with_or_without_spans(sess, definitions, cstore, source_span, always_ignore_spans)
+ }
+
+ /// Allow hashing
+ #[inline]
+ pub fn while_hashing_hir_bodies(&mut self, hb: bool, f: impl FnOnce(&mut Self)) {
+ let prev = match &mut self.body_resolver {
+ BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."),
+ BodyResolver::Traverse { ref mut hash_bodies, .. } => {
+ std::mem::replace(hash_bodies, hb)
+ }
+ };
+ f(self);
+ match &mut self.body_resolver {
+ BodyResolver::Forbidden => unreachable!(),
+ BodyResolver::Traverse { ref mut hash_bodies, .. } => *hash_bodies = prev,
+ }
+ }
+
+ #[inline]
+ pub fn with_hir_bodies(
+ &mut self,
+ hash_bodies: bool,
+ owner: LocalDefId,
+ bodies: &SortedMap<hir::ItemLocalId, &hir::Body<'_>>,
+ f: impl FnOnce(&mut StableHashingContext<'_>),
+ ) {
+ f(&mut StableHashingContext {
+ body_resolver: BodyResolver::Traverse { hash_bodies, owner, bodies },
+ ..self.clone()
+ });
+ }
+
+ #[inline]
+ pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
+ let prev_hash_spans = self.hashing_controls.hash_spans;
+ self.hashing_controls.hash_spans = hash_spans;
+ f(self);
+ self.hashing_controls.hash_spans = prev_hash_spans;
+ }
+
+ #[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 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 {
+ ich::IGNORED_ATTRIBUTES.contains(&name)
+ }
+
+ #[inline]
+ pub fn hashing_controls(&self) -> HashingControls {
+ self.hashing_controls.clone()
+ }
+}
+
+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.hashing_controls.hash_spans
+ }
+
+ #[inline]
+ fn unstable_opts_incremental_ignore_spans(&self) -> bool {
+ self.incremental_ignore_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.source_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)
+ }
+
+ #[inline]
+ fn hashing_controls(&self) -> HashingControls {
+ self.hashing_controls.clone()
+ }
+}
+
+impl<'a> rustc_data_structures::intern::InternedHashingContext for StableHashingContext<'a> {
+ fn with_def_path_and_no_spans(&mut self, f: impl FnOnce(&mut Self)) {
+ self.while_hashing_spans(false, f);
+ }
+}
+
+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 000000000..3390ed9eb
--- /dev/null
+++ b/compiler/rustc_query_system/src/ich/impls_hir.rs
@@ -0,0 +1,42 @@
+//! This module contains `HashStable` implementations for various HIR data
+//! types in no particular order.
+
+use crate::ich::hcx::BodyResolver;
+use crate::ich::StableHashingContext;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir as hir;
+
+impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
+ #[inline]
+ fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) {
+ let hcx = self;
+ match hcx.body_resolver {
+ BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."),
+ BodyResolver::Traverse { hash_bodies: false, .. } => {}
+ BodyResolver::Traverse { hash_bodies: true, owner, bodies } => {
+ assert_eq!(id.hir_id.owner, owner);
+ bodies[&id.hir_id.local_id].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;
+
+ hir_id.hash_stable(hcx, hasher);
+ 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;
+
+ hir_id.hash_stable(hcx, hasher);
+ kind.hash_stable(hcx, hasher);
+ span.hash_stable(hcx, hasher);
+ })
+ }
+}
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 000000000..1fa085926
--- /dev/null
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -0,0 +1,150 @@
+//! 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: _,
+ 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 are always in `Lines` form by the time we reach here.
+ assert!(self.lines.borrow().is_lines());
+ self.lines(|lines| {
+ // 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 000000000..0a1c350b2
--- /dev/null
+++ b/compiler/rustc_query_system/src/ich/mod.rs
@@ -0,0 +1,19 @@
+//! ICH - Incremental Compilation Hash
+
+pub use self::hcx::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,
+];