Skip to content

Commit 12bab02

Browse files
committed
Fix hashing cache issue
1 parent 4ca8136 commit 12bab02

File tree

12 files changed

+112
-47
lines changed

12 files changed

+112
-47
lines changed

compiler/rustc_data_structures/src/stable_hasher.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::fx::FxHashMap;
12
use crate::sip128::SipHasher128;
23
use rustc_index::bit_set;
34
use rustc_index::vec;
@@ -584,3 +585,28 @@ fn stable_hash_reduce<HCX, I, C, F>(
584585
}
585586
}
586587
}
588+
589+
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
590+
pub enum NodeIdHashingMode {
591+
Ignore,
592+
HashDefPath,
593+
}
594+
595+
/// Controls what data we do or not not hash.
596+
/// Whenever a `HashStable` implementation caches its
597+
/// result, it needs to include `HashingControls` as part
598+
/// of the key, to ensure that is does not produce an incorrect
599+
/// result (for example, using a `Fingerprint` produced while
600+
/// hashing `Span`s when a `Fingeprint` without `Span`s is
601+
/// being requested)
602+
#[derive(Clone, Hash, Eq, PartialEq, Debug)]
603+
pub struct HashingControls {
604+
pub hash_spans: bool,
605+
pub node_id_hashing_mode: NodeIdHashingMode,
606+
}
607+
608+
/// A cache for use by `HashStable` implementations. It includes
609+
/// a `HashingControls` as part of the key, to prevent using
610+
/// a result computed under one `HashingControls` with a different
611+
/// `HashingControls`
612+
pub type StableHashCache<K, V> = FxHashMap<(K, HashingControls), V>;

compiler/rustc_middle/src/ty/adt.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_data_structures::captures::Captures;
55
use rustc_data_structures::fingerprint::Fingerprint;
66
use rustc_data_structures::fx::FxHashMap;
77
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
8+
use rustc_data_structures::stable_hasher::HashingControls;
89
use rustc_errors::ErrorReported;
910
use rustc_hir as hir;
1011
use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -136,12 +137,13 @@ impl Hash for AdtDef {
136137
impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
137138
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
138139
thread_local! {
139-
static CACHE: RefCell<FxHashMap<usize, Fingerprint>> = Default::default();
140+
static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default();
140141
}
141142

142143
let hash: Fingerprint = CACHE.with(|cache| {
143144
let addr = self as *const AdtDef as usize;
144-
*cache.borrow_mut().entry(addr).or_insert_with(|| {
145+
let hashing_controls = hcx.hashing_controls();
146+
*cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| {
145147
let ty::AdtDef { did, ref variants, ref flags, ref repr } = *self;
146148

147149
let mut hasher = StableHasher::new();

compiler/rustc_middle/src/ty/impls_ty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::ty;
77
use rustc_data_structures::fingerprint::Fingerprint;
88
use rustc_data_structures::fx::FxHashMap;
99
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
10+
use rustc_data_structures::stable_hasher::HashingControls;
1011
use rustc_query_system::ich::StableHashingContext;
1112
use std::cell::RefCell;
1213
use std::mem;
@@ -17,12 +18,12 @@ where
1718
{
1819
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
1920
thread_local! {
20-
static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
21+
static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
2122
RefCell::new(Default::default());
2223
}
2324

2425
let hash = CACHE.with(|cache| {
25-
let key = (self.as_ptr() as usize, self.len());
26+
let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls());
2627
if let Some(&hash) = cache.borrow().get(&key) {
2728
return hash;
2829
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,7 @@ pub enum VariantDiscr {
15971597
#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
15981598
pub struct FieldDef {
15991599
pub did: DefId,
1600+
#[stable_hasher(project(name))]
16001601
pub ident: Ident,
16011602
pub vis: Visibility,
16021603
}

compiler/rustc_middle/src/ty/util.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ impl<'tcx> TyCtxt<'tcx> {
137137

138138
hcx.while_hashing_spans(false, |hcx| {
139139
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
140+
tracing::info!("Hashing: {:?}", ty);
140141
ty.hash_stable(hcx, &mut hasher);
142+
tracing::info!("Done hashing: {:?}", ty);
141143
});
142144
});
143145
hasher.finish()

compiler/rustc_query_system/src/ich/hcx.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_ast as ast;
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_data_structures::sorted_map::SortedMap;
55
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
6+
use rustc_data_structures::stable_hasher::{HashingControls, NodeIdHashingMode};
67
use rustc_data_structures::sync::Lrc;
78
use rustc_hir as hir;
89
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -27,19 +28,11 @@ pub struct StableHashingContext<'a> {
2728
definitions: &'a Definitions,
2829
cstore: &'a dyn CrateStore,
2930
pub(super) body_resolver: BodyResolver<'a>,
30-
hash_spans: bool,
31-
pub(super) node_id_hashing_mode: NodeIdHashingMode,
32-
3331
// Very often, we are hashing something that does not need the
3432
// `CachingSourceMapView`, so we initialize it lazily.
3533
raw_source_map: &'a SourceMap,
3634
caching_source_map: Option<CachingSourceMapView<'a>>,
37-
}
38-
39-
#[derive(PartialEq, Eq, Clone, Copy)]
40-
pub enum NodeIdHashingMode {
41-
Ignore,
42-
HashDefPath,
35+
pub(super) hashing_controls: HashingControls,
4336
}
4437

4538
/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`.
@@ -72,8 +65,10 @@ impl<'a> StableHashingContext<'a> {
7265
cstore,
7366
caching_source_map: None,
7467
raw_source_map: sess.source_map(),
75-
hash_spans: hash_spans_initial,
76-
node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
68+
hashing_controls: HashingControls {
69+
hash_spans: hash_spans_initial,
70+
node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
71+
}
7772
}
7873
}
7974

@@ -133,10 +128,10 @@ impl<'a> StableHashingContext<'a> {
133128

134129
#[inline]
135130
pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self, hash_spans: bool, f: F) {
136-
let prev_hash_spans = self.hash_spans;
137-
self.hash_spans = hash_spans;
131+
let prev_hash_spans = self.hashing_controls.hash_spans;
132+
self.hashing_controls.hash_spans = hash_spans;
138133
f(self);
139-
self.hash_spans = prev_hash_spans;
134+
self.hashing_controls.hash_spans = prev_hash_spans;
140135
}
141136

142137
#[inline]
@@ -145,10 +140,10 @@ impl<'a> StableHashingContext<'a> {
145140
mode: NodeIdHashingMode,
146141
f: F,
147142
) {
148-
let prev = self.node_id_hashing_mode;
149-
self.node_id_hashing_mode = mode;
143+
let prev = self.hashing_controls.node_id_hashing_mode;
144+
self.hashing_controls.node_id_hashing_mode = mode;
150145
f(self);
151-
self.node_id_hashing_mode = prev;
146+
self.hashing_controls.node_id_hashing_mode = prev;
152147
}
153148

154149
#[inline]
@@ -183,6 +178,10 @@ impl<'a> StableHashingContext<'a> {
183178
}
184179
IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name))
185180
}
181+
182+
pub fn hashing_controls(&self) -> HashingControls {
183+
self.hashing_controls.clone()
184+
}
186185
}
187186

188187
impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
@@ -195,7 +194,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
195194
impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
196195
#[inline]
197196
fn hash_spans(&self) -> bool {
198-
self.hash_spans
197+
self.hashing_controls.hash_spans
199198
}
200199

201200
#[inline]
@@ -215,6 +214,11 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
215214
) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
216215
self.source_map().span_data_to_lines_and_cols(span)
217216
}
217+
218+
#[inline]
219+
fn hashing_controls(&self) -> HashingControls {
220+
self.hashing_controls.clone()
221+
}
218222
}
219223

220224
impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {}

compiler/rustc_query_system/src/ich/impls_hir.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
1212
#[inline]
1313
fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) {
1414
let hcx = self;
15-
match hcx.node_id_hashing_mode {
15+
match hcx.hashing_controls.node_id_hashing_mode {
1616
NodeIdHashingMode::Ignore => {
1717
// Don't do anything.
1818
}
@@ -112,12 +112,12 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
112112

113113
#[inline]
114114
fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
115-
let prev_hash_node_ids = self.node_id_hashing_mode;
116-
self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
115+
let prev_hash_node_ids = self.hashing_controls.node_id_hashing_mode;
116+
self.hashing_controls.node_id_hashing_mode = NodeIdHashingMode::Ignore;
117117

118118
f(self);
119119

120-
self.node_id_hashing_mode = prev_hash_node_ids;
120+
self.hashing_controls.node_id_hashing_mode = prev_hash_node_ids;
121121
}
122122

123123
#[inline]

compiler/rustc_query_system/src/ich/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! ICH - Incremental Compilation Hash
22
3-
pub use self::hcx::{NodeIdHashingMode, StableHashingContext};
3+
pub use rustc_data_structures::stable_hasher::NodeIdHashingMode;
4+
pub use self::hcx::{StableHashingContext};
45
use rustc_span::symbol::{sym, Symbol};
56

67
mod hcx;

compiler/rustc_span/src/hygiene.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ use crate::{HashStableContext, Span, DUMMY_SP};
3232
use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
3333
use rustc_data_structures::fingerprint::Fingerprint;
3434
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
35-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
35+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, NodeIdHashingMode};
36+
use rustc_data_structures::stable_hasher::HashingControls;
3637
use rustc_data_structures::sync::{Lock, Lrc};
3738
use rustc_data_structures::unhash::UnhashMap;
3839
use rustc_index::vec::IndexVec;
@@ -88,6 +89,22 @@ rustc_index::newtype_index! {
8889
}
8990
}
9091

92+
// Assert that the provided `HashStableContext` is configured with the 'default'
93+
// `HashingControls`. We should always have bailed out before getting to here
94+
// with a non-default mode. With this check in place, we can avoid the need
95+
// to maintain separate versions of `ExpnData` hashes for each permutation
96+
// of `HashingControls` settings.
97+
fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str) {
98+
let default = HashingControls {
99+
hash_spans: true,
100+
node_id_hashing_mode: NodeIdHashingMode::HashDefPath
101+
};
102+
let current = ctx.hashing_controls();
103+
if current != default {
104+
//panic!("Attempted hashing of {msg} with non-default HashingControls: {:?}", current);
105+
}
106+
}
107+
91108
/// A unique hash value associated to an expansion.
92109
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
93110
pub struct ExpnHash(Fingerprint);
@@ -1444,6 +1461,7 @@ fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContex
14441461
"Already set disambiguator for ExpnData: {:?}",
14451462
expn_data
14461463
);
1464+
assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)");
14471465
let mut expn_hash = expn_data.hash_expn(&mut ctx);
14481466

14491467
let disambiguator = HygieneData::with(|data| {
@@ -1493,6 +1511,7 @@ impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
14931511

14941512
impl<CTX: HashStableContext> HashStable<CTX> for ExpnId {
14951513
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
1514+
assert_default_hashing_controls(ctx, "ExpnId");
14961515
let hash = if *self == ExpnId::root() {
14971516
// Avoid fetching TLS storage for a trivial often-used value.
14981517
Fingerprint::ZERO

compiler/rustc_span/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub mod hygiene;
4242
use hygiene::Transparency;
4343
pub use hygiene::{DesugaringKind, ExpnKind, MacroKind};
4444
pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
45+
use rustc_data_structures::stable_hasher::HashingControls;
4546
pub mod def_id;
4647
use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
4748
pub mod lev_distance;
@@ -2062,6 +2063,7 @@ pub trait HashStableContext {
20622063
&mut self,
20632064
span: &SpanData,
20642065
) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)>;
2066+
fn hashing_controls(&self) -> HashingControls;
20652067
}
20662068

20672069
impl<CTX> HashStable<CTX> for Span
@@ -2087,6 +2089,8 @@ where
20872089
return;
20882090
}
20892091

2092+
tracing::info!("Hashing span: {:?}", self);
2093+
20902094
let span = self.data_untracked();
20912095
span.ctxt.hash_stable(ctx, hasher);
20922096
span.parent.hash_stable(ctx, hasher);

compiler/rustc_symbol_mangling/src/legacy.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -113,29 +113,30 @@ fn get_symbol_hash<'tcx>(
113113
hcx.while_hashing_spans(false, |hcx| {
114114
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
115115
item_type.hash_stable(hcx, &mut hasher);
116-
});
117-
});
118116

119-
// If this is a function, we hash the signature as well.
120-
// This is not *strictly* needed, but it may help in some
121-
// situations, see the `run-make/a-b-a-linker-guard` test.
122-
if let ty::FnDef(..) = item_type.kind() {
123-
item_type.fn_sig(tcx).hash_stable(&mut hcx, &mut hasher);
124-
}
117+
// If this is a function, we hash the signature as well.
118+
// This is not *strictly* needed, but it may help in some
119+
// situations, see the `run-make/a-b-a-linker-guard` test.
120+
if let ty::FnDef(..) = item_type.kind() {
121+
item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher);
122+
}
125123

126-
// also include any type parameters (for generic items)
127-
substs.hash_stable(&mut hcx, &mut hasher);
124+
// also include any type parameters (for generic items)
125+
substs.hash_stable(hcx, &mut hasher);
128126

129-
if let Some(instantiating_crate) = instantiating_crate {
130-
tcx.def_path_hash(instantiating_crate.as_def_id())
131-
.stable_crate_id()
132-
.hash_stable(&mut hcx, &mut hasher);
133-
}
127+
if let Some(instantiating_crate) = instantiating_crate {
128+
tcx.def_path_hash(instantiating_crate.as_def_id())
129+
.stable_crate_id()
130+
.hash_stable(hcx, &mut hasher);
131+
}
132+
133+
// We want to avoid accidental collision between different types of instances.
134+
// Especially, `VtableShim`s and `ReifyShim`s may overlap with their original
135+
// instances without this.
136+
discriminant(&instance.def).hash_stable(hcx, &mut hasher);
134137

135-
// We want to avoid accidental collision between different types of instances.
136-
// Especially, `VtableShim`s and `ReifyShim`s may overlap with their original
137-
// instances without this.
138-
discriminant(&instance.def).hash_stable(&mut hcx, &mut hasher);
138+
});
139+
});
139140
});
140141

141142
// 64 bits should be enough to avoid collisions.

src/test/ui/macros/assert-macro-owned.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
#![allow(non_fmt_panics)]
66

7+
use std::any::TypeId;
8+
79
fn main() {
10+
println!("String: {:?}", TypeId::of::<String>());
11+
println!("&'static str: {:?}", TypeId::of::<&'static str>());
812
assert!(false, "test-assert-owned".to_string());
913
}

0 commit comments

Comments
 (0)