diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 897e9cc2a38..f21f949c9f5 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -83,7 +83,14 @@ macro_rules! __impl_stable_hash_field { macro_rules! impl_stable_hash_for { // FIXME(mark-i-m): Some of these should be `?` rather than `*`. See the git blame and change // them back when `?` is supported again. - (enum $enum_name:path { $( $variant:ident $( ( $($field:ident $(-> $delegate:tt)*),* ) )* ),* $(,)* }) => { + (enum $enum_name:path { + $( $variant:ident + // this incorrectly allows specifying both tuple-like and struct-like fields, as in `Variant(a,b){c,d}`, + // when it should be only one or the other + $( ( $($field:ident $(-> $delegate:tt)*),* ) )* + $( { $($named_field:ident $(-> $named_delegate:tt)*),* } )* + ),* $(,)* + }) => { impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $enum_name { #[inline] fn hash_stable(&self, @@ -94,8 +101,9 @@ macro_rules! impl_stable_hash_for { match *self { $( - $variant $( ( $(ref $field),* ) )* => { + $variant $( ( $(ref $field),* ) )* $( { $(ref $named_field),* } )* => { $($( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*)* + $($( __impl_stable_hash_field!($named_field, __ctx, __hasher $(, $named_delegate)*) );*)* } )* } @@ -133,10 +141,11 @@ macro_rules! impl_stable_hash_for { } }; - (impl<$tcx:lifetime $(, $T:ident)*> for struct $struct_name:path { - $($field:ident),* $(,)* + (impl<$tcx:lifetime $(, $lt:lifetime $(: $lt_bound:lifetime)*)* $(, $T:ident)*> for struct $struct_name:path { + $($field:ident $(-> $delegate:tt)*),* $(,)* }) => { - impl<'a, $tcx, $($T,)*> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name + impl<'a, $tcx, $($lt $(: $lt_bound)*,)* $($T,)*> + ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name where $($T: ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>>),* { #[inline] @@ -147,7 +156,7 @@ macro_rules! impl_stable_hash_for { $(ref $field),* } = *self; - $( $field.hash_stable(__ctx, __hasher));* + $( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );* } } }; diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 047a0125f78..cff2288fd87 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -6,9 +6,8 @@ // it is not used by the general miri engine, just by CTFE. use std::hash::{Hash, Hasher}; -use std::mem; -use rustc::ich::{StableHashingContext, StableHashingContextProvider}; +use rustc::ich::StableHashingContextProvider; use rustc::mir; use rustc::mir::interpret::{ AllocId, Pointer, Scalar, @@ -20,7 +19,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::ty::layout::Align; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use syntax::ast::Mutability; use syntax::source_map::Span; @@ -217,23 +216,10 @@ impl_snapshot_for!(struct MemPlace { align -> *align, // just copy alignment verbatim }); -// Can't use the macro here because that does not support named enum fields. -impl<'a> HashStable> for Place { - fn hash_stable( - &self, hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) - { - mem::discriminant(self).hash_stable(hcx, hasher); - match self { - Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher), - - Place::Local { frame, local } => { - frame.hash_stable(hcx, hasher); - local.hash_stable(hcx, hasher); - }, - } - } -} +impl_stable_hash_for!(enum ::interpret::Place { + Ptr(mem_place), + Local { frame, local }, +}); impl<'a, Ctx> Snapshot<'a, Ctx> for Place where Ctx: SnapshotContext<'a>, { @@ -317,20 +303,10 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation } } -// Can't use the macro here because that does not support named enum fields. -impl<'a> HashStable> for StackPopCleanup { - fn hash_stable( - &self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) - { - mem::discriminant(self).hash_stable(hcx, hasher); - match self { - StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher), - StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher), - } - } -} +impl_stable_hash_for!(enum ::interpret::eval_context::StackPopCleanup { + Goto(block), + None { cleanup }, +}); #[derive(Eq, PartialEq)] struct FrameSnapshot<'a, 'tcx: 'a> { @@ -343,28 +319,17 @@ struct FrameSnapshot<'a, 'tcx: 'a> { stmt: usize, } -// Not using the macro because that does not support types depending on two lifetimes -impl<'a, 'mir, 'tcx: 'mir> HashStable> for Frame<'mir, 'tcx> { - fn hash_stable( - &self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { +impl_stable_hash_for!(impl<'tcx, 'mir: 'tcx> for struct Frame<'mir, 'tcx> { + mir, + instance, + span, + return_to_block, + return_place -> (return_place.as_ref().map(|r| &**r)), + locals, + block, + stmt, +}); - let Frame { - mir, - instance, - span, - return_to_block, - return_place, - locals, - block, - stmt, - } = self; - - (mir, instance, span, return_to_block).hash_stable(hcx, hasher); - (return_place.as_ref().map(|r| &**r), locals, block, stmt).hash_stable(hcx, hasher); - } -} impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> where Ctx: SnapshotContext<'a>, { @@ -443,21 +408,11 @@ impl<'a, 'mir, 'tcx> Hash for EvalSnapshot<'a, 'mir, 'tcx> } } -// Not using the macro because we need special handling for `memory`, which the macro -// does not support at the same time as the extra bounds on the type. -impl<'a, 'b, 'mir, 'tcx> HashStable> - for EvalSnapshot<'a, 'mir, 'tcx> -{ - fn hash_stable( - &self, - hcx: &mut StableHashingContext<'b>, - hasher: &mut StableHasher) - { - // Not hashing memory: Avoid hashing memory all the time during execution - let EvalSnapshot{ memory: _, stack } = self; - stack.hash_stable(hcx, hasher); - } -} +impl_stable_hash_for!(impl<'tcx, 'b, 'mir> for struct EvalSnapshot<'b, 'mir, 'tcx> { + // Not hashing memory: Avoid hashing memory all the time during execution + memory -> _, + stack, +}); impl<'a, 'mir, 'tcx> Eq for EvalSnapshot<'a, 'mir, 'tcx> {}