diff options
| author | Aaron Hill <aa1ronham@gmail.com> | 2021-12-24 16:36:33 -0500 |
|---|---|---|
| committer | Aaron Hill <aa1ronham@gmail.com> | 2022-01-05 10:13:28 -0500 |
| commit | 5580e5e1dda4557bdbda14cdb4255a3e6facfe86 (patch) | |
| tree | eefcdd83dd525a4b1596e727b046c7308ac817e4 /compiler/rustc_span/src | |
| parent | 936ce3dab7fd042101767c439362310f8355e859 (diff) | |
| download | rust-5580e5e1dda4557bdbda14cdb4255a3e6facfe86.tar.gz rust-5580e5e1dda4557bdbda14cdb4255a3e6facfe86.zip | |
Ensure that `Fingerprint` caching respects hashing configuration
Fixes #92266 In some `HashStable` impls, we use a cache to avoid re-computing the same `Fingerprint` from the same structure (e.g. an `AdtDef`). However, the `StableHashingContext` used can be configured to perform hashing in different ways (e.g. skipping `Span`s). This configuration information is not included in the cache key, which will cause an incorrect `Fingerprint` to be used if we hash the same structure with different `StableHashingContext` settings. To fix this, the configuration settings of `StableHashingContext` are split out into a separate `HashingControls` struct. This struct is used as part of the cache key, ensuring that our caches always produce the correct result for the given settings. With this in place, we now turn off `Span` hashing during the entire process of computing the hash included in legacy symbols. This current has no effect, but will matter when a future PR starts hashing more `Span`s that we currently skip.
Diffstat (limited to 'compiler/rustc_span/src')
| -rw-r--r-- | compiler/rustc_span/src/hygiene.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 2 |
2 files changed, 26 insertions, 0 deletions
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 315b706fbc4..6bb4f31cbff 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -32,6 +32,7 @@ use crate::{HashStableContext, Span, DUMMY_SP}; use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::stable_hasher::HashingControls; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::unhash::UnhashMap; @@ -88,6 +89,27 @@ rustc_index::newtype_index! { } } +// Assert that the provided `HashStableContext` is configured with the 'default' +// `HashingControls`. We should always have bailed out before getting to here +// with a non-default mode. With this check in place, we can avoid the need +// to maintain separate versions of `ExpnData` hashes for each permutation +// of `HashingControls` settings. +fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str) { + match ctx.hashing_controls() { + // Ideally, we would also check that `node_id_hashing_mode` was always + // `NodeIdHashingMode::HashDefPath`. However, we currently end up hashing + // `Span`s in this mode, and there's not an easy way to change that. + // All of the span-related data that we hash is pretty self-contained + // (in particular, we don't hash any `HirId`s), so this shouldn't result + // in any caching problems. + // FIXME: Enforce that we don't end up transitively hashing any `HirId`s, + // or ensure that this method is always invoked with the same + // `NodeIdHashingMode` + HashingControls { hash_spans: true, node_id_hashing_mode: _ } => {} + other => panic!("Attempted hashing of {msg} with non-default HashingControls: {:?}", other), + } +} + /// A unique hash value associated to an expansion. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] pub struct ExpnHash(Fingerprint); @@ -1444,6 +1466,7 @@ fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContex "Already set disambiguator for ExpnData: {:?}", expn_data ); + assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)"); let mut expn_hash = expn_data.hash_expn(&mut ctx); let disambiguator = HygieneData::with(|data| { @@ -1493,6 +1516,7 @@ impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext { impl<CTX: HashStableContext> HashStable<CTX> for ExpnId { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + assert_default_hashing_controls(ctx, "ExpnId"); let hash = if *self == ExpnId::root() { // Avoid fetching TLS storage for a trivial often-used value. Fingerprint::ZERO diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 3bbf2a0e456..4d60ca481a0 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -42,6 +42,7 @@ pub mod hygiene; use hygiene::Transparency; pub use hygiene::{DesugaringKind, ExpnKind, MacroKind}; pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext}; +use rustc_data_structures::stable_hasher::HashingControls; pub mod def_id; use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE}; pub mod lev_distance; @@ -2062,6 +2063,7 @@ pub trait HashStableContext { &mut self, span: &SpanData, ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)>; + fn hashing_controls(&self) -> HashingControls; } impl<CTX> HashStable<CTX> for Span |
