Move HashStableContext trait to rustc_data_structures.

This puts it in the same crate as the `HashStable` and `ToStableHasher`
traits. This requires introducing three types `RawSpan`, `RawDefId` and
`RawDefPathHash` to work around the fact that `rustc_data_structures`
is upstream of `rustc_span` and so doesn't have access to `Span`,
`DefId`, and `DefPathHash`. This is a bit ugly but is worth it because
moving `HashStableContext` enables big cleanups across many crates in
subsequent commits.
This commit is contained in:
Nicholas Nethercote
2026-04-02 19:41:57 +11:00
parent fc3a9a51f6
commit a6318f677d
15 changed files with 108 additions and 47 deletions
+2 -3
View File
@@ -25,14 +25,13 @@ pub use GenericArgs::*;
pub use UnsafeSource::*;
pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy};
use rustc_data_structures::packed::Pu128;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stable_hasher::{HashStable, HashStableContext, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::tagged_ptr::Tag;
use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable};
pub use rustc_span::AttrId;
use rustc_span::{
ByteSymbol, DUMMY_SP, ErrorGuaranteed, HashStableContext, Ident, Span, Spanned, Symbol, kw,
respan, sym,
ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, respan, sym,
};
use thin_vec::{ThinVec, thin_vec};
+2 -2
View File
@@ -10,11 +10,11 @@ use std::ops::Range;
use std::sync::Arc;
use std::{cmp, fmt, iter, mem};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stable_hasher::{HashStable, HashStableContext, StableHasher};
use rustc_data_structures::sync;
use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, Symbol, sym};
use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym};
use thin_vec::ThinVec;
use crate::ast::AttrStyle;
@@ -15,6 +15,34 @@ pub use rustc_stable_hash::{
FromStableHash, SipHasher128Hash as StableHasherHash, StableSipHasher128 as StableHasher,
};
/// This trait lets `HashStable` and `derive(HashStable_Generic)` be used in
/// this crate (and other crates upstream of `rustc_middle`), while leaving
/// certain operations to be defined in `rustc_middle` where more things are
/// visible.
pub trait HashStableContext {
/// The main event: stable hashing of a span.
fn span_hash_stable(&mut self, span: RawSpan, hasher: &mut StableHasher);
/// Compute a `DefPathHash`.
fn def_path_hash(&self, def_id: RawDefId) -> RawDefPathHash;
/// Assert that the provided `HashStableContext` is configured with the default
/// `HashingControls`. We should always have bailed out before getting to here with a
fn assert_default_hashing_controls(&self, msg: &str);
}
// A type used to work around `Span` not being visible in this crate. It is the same layout as
// `Span`.
pub struct RawSpan(pub u32, pub u16, pub u16);
// A type used to work around `DefId` not being visible in this crate. It is the same size as
// `DefId`.
pub struct RawDefId(pub u32, pub u32);
// A type used to work around `DefPathHash` not being visible in this crate. It is the same size as
// `DefPathHash`.
pub struct RawDefPathHash(pub [u8; 16]);
/// Something that implements `HashStable<Hcx>` can be hashed in a way that is
/// stable across multiple compilation sessions.
///
+2 -2
View File
@@ -4,13 +4,13 @@ use std::fmt::Debug;
use rustc_ast as ast;
use rustc_ast::NodeId;
use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_data_structures::stable_hasher::{HashStableContext, ToStableHashKey};
use rustc_data_structures::unord::UnordMap;
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::MacroKind;
use rustc_span::{HashStableContext, Symbol};
use crate::definitions::DefPathData;
use crate::hir;
+3 -2
View File
@@ -1,5 +1,6 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_span::HashStableContext;
use rustc_data_structures::stable_hasher::{
HashStable, HashStableContext, StableHasher, ToStableHashKey,
};
use rustc_span::def_id::DefPathHash;
use crate::HashIgnoredAttrId;
+3 -2
View File
@@ -6,9 +6,10 @@
use std::fmt::{self, Debug};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_data_structures::stable_hasher::{
HashStable, HashStableContext, StableHasher, StableOrd, ToStableHashKey,
};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::HashStableContext;
use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
+2 -2
View File
@@ -5,14 +5,14 @@ use rustc_ast::AttrId;
use rustc_ast::attr::AttributeExt;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::stable_hasher::{
HashStable, StableCompare, StableHasher, ToStableHashKey,
HashStable, HashStableContext, StableCompare, StableHasher, ToStableHashKey,
};
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
use rustc_hir_id::{HirId, ItemLocalId};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::def_id::DefPathHash;
pub use rustc_span::edition::Edition;
use rustc_span::{HashStableContext, Ident, Symbol, sym};
use rustc_span::{Ident, Symbol, sym};
use serde::{Deserialize, Serialize};
pub use self::Level::*;
+3 -1
View File
@@ -84,7 +84,9 @@ fn hash_stable_derive_with_mode(
match mode {
HashStableMode::Normal => {}
HashStableMode::Generic => {
s.add_where_predicate(parse_quote! { __CTX: ::rustc_span::HashStableContext });
s.add_where_predicate(parse_quote! {
__CTX: ::rustc_data_structures::stable_hasher::HashStableContext
});
}
HashStableMode::NoContext => {}
}
+2 -2
View File
@@ -12,7 +12,7 @@ use rustc_ast::{self as ast};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stable_hasher::{HashStable, HashStableContext, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in};
use rustc_hir::def::{DefKind, Res};
@@ -20,7 +20,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::*;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::{ErrorGuaranteed, ExpnId, HashStableContext, Span};
use rustc_span::{ErrorGuaranteed, ExpnId, Span};
use crate::query::Providers;
use crate::ty::{ResolverAstLowering, TyCtxt};
+9 -5
View File
@@ -1,12 +1,13 @@
use std::hash::Hash;
use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
use rustc_data_structures::stable_hasher::{
HashStable, HashStableContext, HashingControls, RawDefId, RawDefPathHash, RawSpan, StableHasher,
};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::definitions::DefPathHash;
use rustc_session::Session;
use rustc_session::cstore::Untracked;
use rustc_span::source_map::SourceMap;
use rustc_span::{CachingSourceMapView, DUMMY_SP, HashStableContext, Pos, Span};
use rustc_span::{CachingSourceMapView, DUMMY_SP, Pos, Span};
// Very often, we are hashing something that does not need the `CachingSourceMapView`, so we
// initialize it lazily.
@@ -84,7 +85,7 @@ impl<'a> HashStableContext for StableHashingContext<'a> {
///
/// IMPORTANT: changes to this method should be reflected in implementations of `SpanEncoder`.
#[inline]
fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher) {
fn span_hash_stable(&mut self, raw_span: RawSpan, hasher: &mut StableHasher) {
const TAG_VALID_SPAN: u8 = 0;
const TAG_INVALID_SPAN: u8 = 1;
const TAG_RELATIVE_SPAN: u8 = 2;
@@ -93,6 +94,7 @@ impl<'a> HashStableContext for StableHashingContext<'a> {
return;
}
let span = Span::from_raw_span(raw_span);
let span = span.data_untracked();
span.ctxt.hash_stable(self, hasher);
span.parent.hash_stable(self, hasher);
@@ -157,12 +159,14 @@ impl<'a> HashStableContext for StableHashingContext<'a> {
}
#[inline]
fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
fn def_path_hash(&self, raw_def_id: RawDefId) -> RawDefPathHash {
let def_id = DefId::from_raw_def_id(raw_def_id);
if let Some(def_id) = def_id.as_local() {
self.untracked.definitions.read().def_path_hash(def_id)
} else {
self.untracked.cstore.read().def_path_hash(def_id)
}
.to_raw_def_path_hash()
}
/// Assert that the provided `HashStableContext` is configured with the default
+4 -3
View File
@@ -14,7 +14,9 @@ use std::{cmp, fs, iter};
use externs::{ExternOpt, split_extern_opt};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
use rustc_data_structures::stable_hasher::{
HashStableContext, StableHasher, StableOrd, ToStableHashKey,
};
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, DiagCtxtFlags};
use rustc_feature::UnstableFeatures;
@@ -23,8 +25,7 @@ use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::{
FileName, HashStableContext, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm,
Symbol, sym,
FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym,
};
use rustc_target::spec::{
FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
+28 -3
View File
@@ -3,14 +3,17 @@ use std::hash::{BuildHasherDefault, Hash, Hasher};
use rustc_data_structures::AtomicRef;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_data_structures::stable_hasher::{
HashStable, HashStableContext, RawDefId, RawDefPathHash, StableHasher, StableOrd,
ToStableHashKey,
};
use rustc_data_structures::unhash::Unhasher;
use rustc_hashes::Hash64;
use rustc_index::Idx;
use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
use rustc_serialize::{Decodable, Encodable};
use crate::{HashStableContext, SpanDecoder, SpanEncoder, Symbol};
use crate::{SpanDecoder, SpanEncoder, Symbol};
pub type StableCrateIdMap =
indexmap::IndexMap<StableCrateId, CrateNum, BuildHasherDefault<Unhasher>>;
@@ -114,6 +117,16 @@ impl DefPathHash {
pub fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> DefPathHash {
DefPathHash(Fingerprint::new(stable_crate_id.0, local_hash))
}
#[inline]
pub fn to_raw_def_path_hash(self) -> RawDefPathHash {
RawDefPathHash(self.0.to_le_bytes())
}
#[inline]
pub fn from_raw_def_path_hash(RawDefPathHash(a): RawDefPathHash) -> DefPathHash {
DefPathHash(Fingerprint::from_le_bytes(a))
}
}
impl Default for DefPathHash {
@@ -312,6 +325,18 @@ impl DefId {
pub fn is_top_level_module(self) -> bool {
self.is_local() && self.is_crate_root()
}
#[inline]
pub fn to_raw_def_id(self) -> RawDefId {
// Field order must match `from_raw_def_id`.
RawDefId(self.krate.as_u32(), self.index.as_u32())
}
#[inline]
pub fn from_raw_def_id(RawDefId(a, b): RawDefId) -> DefId {
// Field order must match `to_raw_def_id`.
DefId { krate: a.into(), index: b.into() }
}
}
impl From<LocalDefId> for DefId {
@@ -428,7 +453,7 @@ impl<Hcx: HashStableContext> ToStableHashKey<Hcx> for DefId {
#[inline]
fn to_stable_hash_key(&self, hcx: &mut Hcx) -> DefPathHash {
hcx.def_path_hash(*self)
DefPathHash::from_raw_def_path_hash(hcx.def_path_hash(self.to_raw_def_id()))
}
}
+4 -2
View File
@@ -30,7 +30,9 @@ use std::{fmt, iter, mem};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_data_structures::stable_hasher::{
HashStable, HashStableContext, StableHasher, ToStableHashKey,
};
use rustc_data_structures::sync::Lock;
use rustc_data_structures::unhash::UnhashMap;
use rustc_hashes::Hash64;
@@ -43,7 +45,7 @@ use crate::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, StableCrateId};
use crate::edition::Edition;
use crate::source_map::SourceMap;
use crate::symbol::{Symbol, kw, sym};
use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals};
use crate::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, with_session_globals};
/// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
///
+3 -18
View File
@@ -31,6 +31,7 @@
extern crate self as rustc_span;
use derive_where::derive_where;
use rustc_data_structures::stable_hasher::HashStableContext;
use rustc_data_structures::{AtomicRef, outline};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
@@ -53,7 +54,7 @@ pub use hygiene::{
DesugaringKind, ExpnData, ExpnHash, ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext,
};
pub mod def_id;
use def_id::{CrateNum, DefId, DefIndex, DefPathHash, LOCAL_CRATE, LocalDefId, StableCrateId};
use def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
pub mod edit_distance;
mod span_encoding;
pub use span_encoding::{DUMMY_SP, Span};
@@ -2796,29 +2797,13 @@ impl InnerSpan {
}
}
/// This trait lets `HashStable` and `derive(HashStable_Generic)` be used in
/// this crate (and other crates upstream of `rustc_middle`), while leaving
/// certain operations to be defined in `rustc_middle` where more things are
/// visible.
pub trait HashStableContext {
/// The main event: stable hashing of a span.
fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher);
/// Compute a `DefPathHash`.
fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
/// Assert that the provided `HashStableContext` is configured with the default
/// `HashingControls`. We should always have bailed out before getting to here with a
fn assert_default_hashing_controls(&self, msg: &str);
}
impl<Hcx> HashStable<Hcx> for Span
where
Hcx: HashStableContext,
{
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
// `span_hash_stable` does all the work.
hcx.span_hash_stable(*self, hasher)
hcx.span_hash_stable(self.to_raw_span(), hasher)
}
}
+13
View File
@@ -1,4 +1,5 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::stable_hasher::RawSpan;
// This code is very hot and uses lots of arithmetic, avoid overflow checks for performance.
// See https://github.com/rust-lang/rust/pull/119440#issuecomment-1874255727
use rustc_serialize::int_overflow::DebugStrictAdd;
@@ -441,6 +442,18 @@ impl Span {
Interned(span) => interned_parent(span.index),
}
}
#[inline]
pub(crate) fn to_raw_span(self) -> RawSpan {
// Field order must match `from_raw_span`.
RawSpan(self.lo_or_index, self.len_with_tag_or_marker, self.ctxt_or_parent_or_marker)
}
#[inline]
pub fn from_raw_span(RawSpan(a, b, c): RawSpan) -> Span {
// Field order must match `to_raw_span`.
Span { lo_or_index: a, len_with_tag_or_marker: b, ctxt_or_parent_or_marker: c }
}
}
#[derive(Default)]