Skip to content

Commit a083aa0

Browse files
committed
Implement Hash in terms of HashStable for EvalSnapshot
1 parent 0300774 commit a083aa0

File tree

8 files changed

+105
-52
lines changed

8 files changed

+105
-52
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
412412
ty::tls::with_opt(|tcx| {
413413
trace!("hashing {:?}", *self);
414414
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
415-
let alloc_kind = tcx.alloc_map.lock().get(*self).expect("no value for AllocId");
415+
let alloc_kind = tcx.alloc_map.lock().get(*self);
416416
alloc_kind.hash_stable(hcx, hasher);
417417
});
418418
}

src/librustc_data_structures/stable_hasher.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,23 @@ impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
281281
}
282282
}
283283

284+
impl<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
285+
where T1: HashStable<CTX>,
286+
T2: HashStable<CTX>,
287+
T3: HashStable<CTX>,
288+
T4: HashStable<CTX>,
289+
{
290+
fn hash_stable<W: StableHasherResult>(&self,
291+
ctx: &mut CTX,
292+
hasher: &mut StableHasher<W>) {
293+
let (ref _0, ref _1, ref _2, ref _3) = *self;
294+
_0.hash_stable(ctx, hasher);
295+
_1.hash_stable(ctx, hasher);
296+
_2.hash_stable(ctx, hasher);
297+
_3.hash_stable(ctx, hasher);
298+
}
299+
}
300+
284301
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
285302
default fn hash_stable<W: StableHasherResult>(&self,
286303
ctx: &mut CTX,

src/librustc_mir/const_eval.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
196196
}
197197
}
198198

199+
impl_stable_hash_for!(struct CompileTimeEvaluator {});
200+
199201
#[derive(Clone, Debug)]
200202
enum ConstEvalError {
201203
NeedsRfc(String),

src/librustc_mir/interpret/eval_context.rs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ use std::mem;
1515
use rustc::hir::def_id::DefId;
1616
use rustc::hir::def::Def;
1717
use rustc::hir::map::definitions::DefPathData;
18+
use rustc::ich::{StableHashingContext, StableHashingContextProvider};
1819
use rustc::mir;
1920
use rustc::ty::layout::{
2021
self, Size, Align, HasDataLayout, LayoutOf, TyLayout
2122
};
2223
use rustc::ty::subst::{Subst, Substs};
2324
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
2425
use rustc::ty::query::TyCtxtAt;
25-
use rustc_data_structures::fx::{FxHashSet, FxHasher};
26+
use rustc_data_structures::fx::FxHashSet;
2627
use rustc_data_structures::indexed_vec::IndexVec;
28+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
2729
use rustc::mir::interpret::{
2830
GlobalId, Scalar, FrameInfo,
2931
EvalResult, EvalErrorKind,
@@ -134,25 +136,21 @@ impl<'mir, 'tcx: 'mir> PartialEq for Frame<'mir, 'tcx> {
134136
}
135137
}
136138

137-
impl<'mir, 'tcx: 'mir> Hash for Frame<'mir, 'tcx> {
138-
fn hash<H: Hasher>(&self, state: &mut H) {
139+
impl<'a, 'mir, 'tcx: 'mir> HashStable<StableHashingContext<'a>> for Frame<'mir, 'tcx> {
140+
fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher<W>) {
139141
let Frame {
140-
mir: _,
142+
mir,
141143
instance,
142-
span: _,
144+
span,
143145
return_to_block,
144146
return_place,
145147
locals,
146148
block,
147149
stmt,
148150
} = self;
149151

150-
instance.hash(state);
151-
return_to_block.hash(state);
152-
return_place.hash(state);
153-
locals.hash(state);
154-
block.hash(state);
155-
stmt.hash(state);
152+
(mir, instance, span, return_to_block).hash_stable(hcx, hasher);
153+
(return_place, locals, block, stmt).hash_stable(hcx, hasher);
156154
}
157155
}
158156

@@ -168,6 +166,15 @@ pub enum StackPopCleanup {
168166
None { cleanup: bool },
169167
}
170168

169+
impl<'a> HashStable<StableHashingContext<'a>> for StackPopCleanup {
170+
fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'b>, hasher: &mut StableHasher<W>) {
171+
match self {
172+
StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher),
173+
StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher),
174+
}
175+
}
176+
}
177+
171178
// State of a local variable
172179
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
173180
pub enum LocalValue {
@@ -195,9 +202,14 @@ impl<'tcx> LocalValue {
195202
}
196203
}
197204

205+
impl_stable_hash_for!(enum self::LocalValue {
206+
Dead,
207+
Live(x),
208+
});
209+
198210
/// The virtual machine state during const-evaluation at a given point in time.
199-
#[derive(Eq, PartialEq, Hash)]
200-
pub(crate) struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
211+
#[derive(Eq, PartialEq)]
212+
struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
201213
machine: M,
202214
memory: Memory<'a, 'mir, 'tcx, M>,
203215
stack: Vec<Frame<'mir, 'tcx>>,
@@ -215,6 +227,27 @@ impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M>
215227
}
216228
}
217229

230+
impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M>
231+
where M: Machine<'mir, 'tcx>,
232+
{
233+
fn hash<H: Hasher>(&self, state: &mut H) {
234+
// Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2)
235+
let mut hcx = self.memory.tcx.get_stable_hashing_context();
236+
let mut hasher = StableHasher::<u64>::new();
237+
self.hash_stable(&mut hcx, &mut hasher);
238+
hasher.finish().hash(state)
239+
}
240+
}
241+
242+
impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>> for EvalSnapshot<'a, 'mir, 'tcx, M>
243+
where M: Machine<'mir, 'tcx>,
244+
{
245+
fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'b>, hasher: &mut StableHasher<W>) {
246+
let EvalSnapshot{ machine, memory, stack } = self;
247+
(machine, &memory.data, stack).hash_stable(hcx, hasher);
248+
}
249+
}
250+
218251
pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
219252
/// The set of all `EvalSnapshot` *hashes* observed by this detector.
220253
///
@@ -258,9 +291,10 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
258291
stack: &[Frame<'mir, 'tcx>],
259292
) -> EvalResult<'tcx, ()> {
260293

261-
let mut fx = FxHasher::default();
262-
(machine, memory, stack).hash(&mut fx);
263-
let hash = fx.finish();
294+
let mut hcx = memory.tcx.get_stable_hashing_context();
295+
let mut hasher = StableHasher::<u64>::new();
296+
(machine, stack).hash_stable(&mut hcx, &mut hasher);
297+
let hash = hasher.finish();
264298

265299
if self.hashes.insert(hash) {
266300
// No collision

src/librustc_mir/interpret/machine.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,19 @@
1515
use std::hash::Hash;
1616

1717
use rustc::hir::def_id::DefId;
18+
use rustc::ich::StableHashingContext;
1819
use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
1920
use rustc::mir;
2021
use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
22+
use rustc_data_structures::stable_hasher::HashStable;
2123

2224
use super::{EvalContext, PlaceTy, OpTy};
2325

2426
/// Methods of this trait signifies a point where CTFE evaluation would fail
2527
/// and some use case dependent behaviour can instead be applied
26-
pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
28+
pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>> {
2729
/// Additional data that can be accessed via the Memory
28-
type MemoryData: Clone + Eq + Hash;
30+
type MemoryData: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>>;
2931

3032
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
3133
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;

src/librustc_mir/interpret/memory.rs

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
//! short-circuiting the empty case!
1818
1919
use std::collections::VecDeque;
20-
use std::hash::{Hash, Hasher};
2120
use std::ptr;
2221

2322
use rustc::ty::{self, Instance, query::TyCtxtAt};
@@ -26,7 +25,7 @@ use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, ScalarMayb
2625
EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
2726
truncate};
2827
pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
29-
use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
28+
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
3029

3130
use syntax::ast::Mutability;
3231

@@ -91,37 +90,6 @@ impl<'a, 'mir, 'tcx, M> PartialEq for Memory<'a, 'mir, 'tcx, M>
9190
}
9291
}
9392

94-
impl<'a, 'mir, 'tcx, M> Hash for Memory<'a, 'mir, 'tcx, M>
95-
where M: Machine<'mir, 'tcx>,
96-
'tcx: 'a + 'mir,
97-
{
98-
fn hash<H: Hasher>(&self, state: &mut H) {
99-
let Memory {
100-
data,
101-
alloc_map: _,
102-
tcx: _,
103-
} = self;
104-
105-
data.hash(state);
106-
107-
// We ignore some fields which don't change between evaluation steps.
108-
109-
// Since HashMaps which contain the same items may have different
110-
// iteration orders, we use a commutative operation (in this case
111-
// addition, but XOR would also work), to combine the hash of each
112-
// `Allocation`.
113-
self.alloc_map.iter()
114-
.map(|(&id, alloc)| {
115-
let mut h = FxHasher::default();
116-
id.hash(&mut h);
117-
alloc.hash(&mut h);
118-
h.finish()
119-
})
120-
.fold(0u64, |hash, x| hash.wrapping_add(x))
121-
.hash(state);
122-
}
123-
}
124-
12593
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
12694
pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
12795
Memory {

src/librustc_mir/interpret/operand.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ impl<'tcx> Value {
8181
}
8282
}
8383

84+
impl_stable_hash_for!(enum ::interpret::Value {
85+
Scalar(x),
86+
ScalarPair(x, y),
87+
});
88+
8489
// ScalarPair needs a type to interpret, so we often have a value and a type together
8590
// as input for binary and cast operations.
8691
#[derive(Copy, Clone, Debug)]
@@ -126,6 +131,11 @@ impl Operand {
126131
}
127132
}
128133

134+
impl_stable_hash_for!(enum ::interpret::Operand {
135+
Immediate(x),
136+
Indirect(x),
137+
});
138+
129139
#[derive(Copy, Clone, Debug)]
130140
pub struct OpTy<'tcx> {
131141
crate op: Operand, // ideally we'd make this private, but const_prop needs this

src/librustc_mir/interpret/place.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
1515
use std::convert::TryFrom;
1616

17+
use rustc::ich::StableHashingContext;
1718
use rustc::mir;
1819
use rustc::ty::{self, Ty};
1920
use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
2021
use rustc_data_structures::indexed_vec::Idx;
22+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
2123

2224
use rustc::mir::interpret::{
2325
GlobalId, Scalar, EvalResult, Pointer, ScalarMaybeUndef, PointerArithmetic
@@ -37,6 +39,12 @@ pub struct MemPlace {
3739
pub extra: Option<Scalar>,
3840
}
3941

42+
impl_stable_hash_for!(struct ::interpret::MemPlace {
43+
ptr,
44+
align,
45+
extra,
46+
});
47+
4048
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
4149
pub enum Place {
4250
/// A place referring to a value allocated in the `Memory` system.
@@ -50,6 +58,18 @@ pub enum Place {
5058
},
5159
}
5260

61+
impl<'a> HashStable<StableHashingContext<'a>> for Place {
62+
fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher<W>) {
63+
match self {
64+
Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher),
65+
66+
Place::Local { frame, local } => {
67+
frame.hash_stable(hcx, hasher);
68+
local.hash_stable(hcx, hasher);
69+
},
70+
}
71+
}
72+
}
5373
#[derive(Copy, Clone, Debug)]
5474
pub struct PlaceTy<'tcx> {
5575
place: Place,

0 commit comments

Comments
 (0)