Skip to content

Commit 3cb736a

Browse files
committed
miri loop detector hashing: fix enum hashing to also consider discriminant; do not hash extra machine state
standalone miri is not interested in loop detection
1 parent dac7602 commit 3cb736a

File tree

6 files changed

+38
-26
lines changed

6 files changed

+38
-26
lines changed

src/librustc_mir/const_eval.rs

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
239239
type MemoryKinds = !;
240240

241241
const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
242+
const DETECT_LOOPS: bool = true;
242243

243244
fn find_fn<'a>(
244245
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,

src/librustc_mir/interpret/eval_context.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
6565
/// detector period.
6666
pub(super) steps_since_detector_enabled: isize,
6767

68+
/// Extra state to detect loops.
69+
/// FIXME: Move this to the CTFE machine's state, out of the general miri engine.
6870
pub(super) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>,
6971
}
7072

@@ -110,6 +112,7 @@ pub struct Frame<'mir, 'tcx: 'mir> {
110112
pub stmt: usize,
111113
}
112114

115+
// Not using the macro because that does not support types depending on 'tcx
113116
impl<'a, 'mir, 'tcx: 'mir> HashStable<StableHashingContext<'a>> for Frame<'mir, 'tcx> {
114117
fn hash_stable<W: StableHasherResult>(
115118
&self,
@@ -144,11 +147,14 @@ pub enum StackPopCleanup {
144147
None { cleanup: bool },
145148
}
146149

150+
// Can't use the macro here because that does not support named enum fields.
147151
impl<'a> HashStable<StableHashingContext<'a>> for StackPopCleanup {
148152
fn hash_stable<W: StableHasherResult>(
149153
&self,
150154
hcx: &mut StableHashingContext<'a>,
151-
hasher: &mut StableHasher<W>) {
155+
hasher: &mut StableHasher<W>)
156+
{
157+
mem::discriminant(self).hash_stable(hcx, hasher);
152158
match self {
153159
StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher),
154160
StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher),

src/librustc_mir/interpret/machine.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,29 @@
1212
//! This separation exists to ensure that no fancy miri features like
1313
//! interpreting common C functions leak into CTFE.
1414
15-
use std::hash::Hash;
16-
1715
use rustc::hir::def_id::DefId;
18-
use rustc::ich::StableHashingContext;
1916
use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
2017
use rustc::mir;
2118
use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
22-
use rustc_data_structures::stable_hasher::HashStable;
2319

2420
use super::{EvalContext, PlaceTy, OpTy};
2521

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

3228
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
33-
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;
29+
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq;
3430

3531
/// The memory kind to use for mutated statics -- or None if those are not supported.
3632
const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
3733

34+
/// Whether to attempt to detect infinite loops (any kind of infinite
35+
/// execution, really).
36+
const DETECT_LOOPS: bool;
37+
3838
/// Entry point to all function calls.
3939
///
4040
/// Returns either the mir to use for the call, or `None` if execution should

src/librustc_mir/interpret/place.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! All high-level functions to write to memory work on places as destinations.
1414
1515
use std::convert::TryFrom;
16+
use std::mem;
1617

1718
use rustc::ich::StableHashingContext;
1819
use rustc::mir;
@@ -57,11 +58,13 @@ pub enum Place<Id=AllocId> {
5758
},
5859
}
5960

61+
// Can't use the macro here because that does not support named enum fields.
6062
impl<'a> HashStable<StableHashingContext<'a>> for Place {
6163
fn hash_stable<W: StableHasherResult>(
6264
&self, hcx: &mut StableHashingContext<'a>,
63-
hasher: &mut StableHasher<W>) {
64-
65+
hasher: &mut StableHasher<W>)
66+
{
67+
mem::discriminant(self).hash_stable(hcx, hasher);
6568
match self {
6669
Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher),
6770

src/librustc_mir/interpret/snapshot.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,13 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
6262
pub fn observe_and_analyze(
6363
&mut self,
6464
tcx: &TyCtxt<'b, 'tcx, 'tcx>,
65-
machine: &M,
6665
memory: &Memory<'a, 'mir, 'tcx, M>,
6766
stack: &[Frame<'mir, 'tcx>],
6867
) -> EvalResult<'tcx, ()> {
6968

7069
let mut hcx = tcx.get_stable_hashing_context();
7170
let mut hasher = StableHasher::<u64>::new();
72-
(machine, stack).hash_stable(&mut hcx, &mut hasher);
71+
stack.hash_stable(&mut hcx, &mut hasher);
7372
let hash = hasher.finish();
7473

7574
if self.hashes.insert(hash) {
@@ -79,7 +78,7 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
7978

8079
info!("snapshotting the state of the interpreter");
8180

82-
if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) {
81+
if self.snapshots.insert(EvalSnapshot::new(memory, stack)) {
8382
// Spurious collision or first cycle
8483
return Ok(())
8584
}
@@ -345,7 +344,6 @@ impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M>
345344

346345
/// The virtual machine state during const-evaluation at a given point in time.
347346
struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
348-
machine: M,
349347
memory: Memory<'a, 'mir, 'tcx, M>,
350348
stack: Vec<Frame<'mir, 'tcx>>,
351349
}
@@ -354,21 +352,20 @@ impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M>
354352
where M: Machine<'mir, 'tcx>,
355353
{
356354
fn new(
357-
machine: &M,
358355
memory: &Memory<'a, 'mir, 'tcx, M>,
359-
stack: &[Frame<'mir, 'tcx>]) -> Self {
360-
356+
stack: &[Frame<'mir, 'tcx>]
357+
) -> Self {
361358
EvalSnapshot {
362-
machine: machine.clone(),
363359
memory: memory.clone(),
364360
stack: stack.into(),
365361
}
366362
}
367363

368364
fn snapshot<'b: 'a>(&'b self)
369-
-> (&'b M, MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>) {
370-
let EvalSnapshot{ machine, memory, stack } = self;
371-
(&machine, memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
365+
-> (MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>)
366+
{
367+
let EvalSnapshot{ memory, stack } = self;
368+
(memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
372369
}
373370
}
374371

@@ -384,17 +381,19 @@ impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M>
384381
}
385382
}
386383

384+
// Not using the macro because we need special handling for `memory`, which the macro
385+
// does not support at the same time as the extra bounds on the type.
387386
impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>>
388387
for EvalSnapshot<'a, 'mir, 'tcx, M>
389388
where M: Machine<'mir, 'tcx>,
390389
{
391390
fn hash_stable<W: StableHasherResult>(
392391
&self,
393392
hcx: &mut StableHashingContext<'b>,
394-
hasher: &mut StableHasher<W>) {
395-
396-
let EvalSnapshot{ machine, memory, stack } = self;
397-
(machine, &memory.data, stack).hash_stable(hcx, hasher);
393+
hasher: &mut StableHasher<W>)
394+
{
395+
let EvalSnapshot{ memory: _, stack } = self;
396+
stack.hash_stable(hcx, hasher);
398397
}
399398
}
400399

src/librustc_mir/interpret/step.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
6565
}
6666
}
6767

68+
if !M::DETECT_LOOPS {
69+
return Ok(());
70+
}
71+
6872
if self.loop_detector.is_empty() {
6973
// First run of the loop detector
7074

@@ -75,7 +79,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
7579

7680
self.loop_detector.observe_and_analyze(
7781
&self.tcx,
78-
&self.machine,
7982
&self.memory,
8083
&self.stack[..],
8184
)

0 commit comments

Comments
 (0)