diff --git a/Cargo.lock b/Cargo.lock index 7eb5d4b464c..5e0880da343 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3720,6 +3720,7 @@ dependencies = [ "rustc_errors", "rustc_index", "rustc_lexer", + "rustc_macros", "rustc_target", "serialize", "smallvec 1.0.0", diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index daa2617bd9e..9bc6d32b7cb 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -22,6 +22,7 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_index = { path = "../librustc_index" } rustc_errors = { path = "../librustc_errors" } rustc_lexer = { path = "../librustc_lexer" } +rustc_macros = { path = "../librustc_macros" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 92358ad247e..471227f7403 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -3,6 +3,7 @@ use std::fmt::Write; use std::mem; use syntax::source_map::{self, Span, DUMMY_SP}; +use rustc::ich::StableHashingContext; use rustc::hir::def_id::DefId; use rustc::hir::def::DefKind; use rustc::mir; @@ -18,6 +19,8 @@ use rustc::mir::interpret::{ InterpResult, truncate, sign_extend, }; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable; use super::{ Immediate, Operand, MemPlace, MPlaceTy, Place, PlaceTy, ScalarMaybeUndef, @@ -93,7 +96,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> { pub stmt: usize, } -#[derive(Clone, Eq, PartialEq, Debug)] // Miri debug-prints these +#[derive(Clone, Eq, PartialEq, Debug, HashStable)] // Miri debug-prints these pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so @@ -109,15 +112,16 @@ pub enum StackPopCleanup { } /// State of a local variable including a memoized layout -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, HashStable)] pub struct LocalState<'tcx, Tag=(), Id=AllocId> { pub value: LocalValue, /// Don't modify if `Some`, this is only used to prevent computing the layout twice + #[stable_hasher(ignore)] pub layout: Cell>>, } /// Current value of a local variable -#[derive(Clone, PartialEq, Eq, Debug)] // Miri debug-prints these +#[derive(Clone, PartialEq, Eq, Debug, HashStable)] // Miri debug-prints these pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, @@ -827,3 +831,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { frames } } + +impl<'ctx, 'mir, 'tcx, Tag, Extra> HashStable> +for Frame<'mir, 'tcx, Tag, Extra> + where Extra: HashStable>, + Tag: HashStable> +{ + fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) { + self.body.hash_stable(hcx, hasher); + self.instance.hash_stable(hcx, hasher); + self.span.hash_stable(hcx, hasher); + self.return_to_block.hash_stable(hcx, hasher); + self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher); + self.locals.hash_stable(hcx, hasher); + self.block.hash_stable(hcx, hasher); + self.stmt.hash_stable(hcx, hasher); + self.extra.hash_stable(hcx, hasher); + } +} diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4d2ccdc20da..cfa70164cdc 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -18,6 +18,7 @@ use super::{ MemPlace, MPlaceTy, PlaceTy, Place, }; pub use rustc::mir::interpret::ScalarMaybeUndef; +use rustc_macros::HashStable; /// An `Immediate` represents a single immediate self-contained Rust value. /// @@ -26,7 +27,7 @@ pub use rustc::mir::interpret::ScalarMaybeUndef; /// operations and fat pointers. This idea was taken from rustc's codegen. /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// defined on `Immediate`, and do not have to work with a `Place`. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] pub enum Immediate { Scalar(ScalarMaybeUndef), ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), @@ -103,7 +104,7 @@ impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> { /// An `Operand` is the result of computing a `mir::Operand`. It can be immediate, /// or still in memory. The latter is an optimization, to delay reading that chunk of /// memory and to avoid having to store arbitrary-sized data here. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] pub enum Operand { Immediate(Immediate), Indirect(MemPlace), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 0bd47edc046..088fbe1695e 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -12,6 +12,7 @@ use rustc::ty::layout::{ self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt }; use rustc::ty::TypeFoldable; +use rustc_macros::HashStable; use super::{ GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic, @@ -19,7 +20,7 @@ use super::{ RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue, }; -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)] pub struct MemPlace { /// A place may have an integral pointer for ZSTs, and since it might /// be turned back into a reference before ever being dereferenced. @@ -32,7 +33,7 @@ pub struct MemPlace { pub meta: Option>, } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)] pub enum Place { /// A place referring to a value allocated in the `Memory` system. Ptr(MemPlace), diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 7f3ea0283cd..3ea00d69221 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -19,6 +19,7 @@ use rustc::ty::layout::{Align, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_index::vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable; use syntax::ast::Mutability; use syntax::source_map::Span; @@ -197,21 +198,12 @@ impl_snapshot_for!(enum ScalarMaybeUndef { Undef, }); -impl_stable_hash_for!(struct crate::interpret::MemPlace { - ptr, - align, - meta, -}); impl_snapshot_for!(struct MemPlace { ptr, meta, align -> *align, // just copy alignment verbatim }); -impl_stable_hash_for!(enum crate::interpret::Place { - Ptr(mem_place), - Local { frame, local }, -}); impl<'a, Ctx> Snapshot<'a, Ctx> for Place where Ctx: SnapshotContext<'a>, { @@ -229,29 +221,16 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for Place } } -impl_stable_hash_for!(enum crate::interpret::Immediate { - Scalar(x), - ScalarPair(x, y), -}); impl_snapshot_for!(enum Immediate { Scalar(s), ScalarPair(s, t), }); -impl_stable_hash_for!(enum crate::interpret::Operand { - Immediate(x), - Indirect(x), -}); impl_snapshot_for!(enum Operand { Immediate(v), Indirect(m), }); -impl_stable_hash_for!(enum crate::interpret::LocalValue { - Dead, - Uninitialized, - Live(x), -}); impl_snapshot_for!(enum LocalValue { Dead, Uninitialized, @@ -314,11 +293,6 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation } } -impl_stable_hash_for!(enum crate::interpret::eval_context::StackPopCleanup { - Goto { ret, unwind }, - None { cleanup }, -}); - #[derive(Eq, PartialEq)] struct FrameSnapshot<'a, 'tcx> { instance: ty::Instance<'tcx>, @@ -330,18 +304,6 @@ struct FrameSnapshot<'a, 'tcx> { stmt: usize, } -impl_stable_hash_for!(impl<> for struct Frame<'mir, 'tcx> { - body, - instance, - span, - return_to_block, - return_place -> (return_place.as_ref().map(|r| &**r)), - locals, - block, - stmt, - extra, -}); - impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> where Ctx: SnapshotContext<'a>, { @@ -383,11 +345,6 @@ impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx> } } -impl_stable_hash_for!(struct LocalState<'tcx> { - value, - layout -> _, -}); - impl<'b, 'mir, 'tcx> SnapshotContext<'b> for Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { @@ -399,7 +356,10 @@ impl<'b, 'mir, 'tcx> SnapshotContext<'b> /// The virtual machine state during const-evaluation at a given point in time. /// We assume the `CompileTimeInterpreter` has no interesting extra state that /// is worth considering here. +#[derive(HashStable)] struct InterpSnapshot<'mir, 'tcx> { + // Not hashing memory: Avoid hashing memory all the time during execution + #[stable_hasher(ignore)] memory: Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, stack: Vec>, } @@ -434,12 +394,6 @@ impl<'mir, 'tcx> Hash for InterpSnapshot<'mir, 'tcx> { } } -impl_stable_hash_for!(impl<> for struct InterpSnapshot<'mir, 'tcx> { - // Not hashing memory: Avoid hashing memory all the time during execution - memory -> _, - stack, -}); - impl<'mir, 'tcx> Eq for InterpSnapshot<'mir, 'tcx> {} impl<'mir, 'tcx> PartialEq for InterpSnapshot<'mir, 'tcx> {