Rollup merge of #55302 - goffrie:impl-stable-hash, r=varkor

Extend the impl_stable_hash_for! macro for miri.

Fixes #54075.
This commit is contained in:
kennytm 2018-10-26 18:25:07 +08:00
commit 9880e29fa1
No known key found for this signature in database
GPG Key ID: FEF6C8051D0E013C
2 changed files with 40 additions and 76 deletions

View File

@ -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<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&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)*) );*
}
}
};

View File

@ -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<StableHashingContext<'a>> for Place {
fn hash_stable<W: StableHasherResult>(
&self, hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>)
{
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<StableHashingContext<'a>> for StackPopCleanup {
fn hash_stable<W: StableHasherResult>(
&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>)
{
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<StableHashingContext<'a>> for Frame<'mir, 'tcx> {
fn hash_stable<W: StableHasherResult>(
&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
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<StableHashingContext<'b>>
for EvalSnapshot<'a, 'mir, 'tcx>
{
fn hash_stable<W: StableHasherResult>(
&self,
hcx: &mut StableHashingContext<'b>,
hasher: &mut StableHasher<W>)
{
// 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>
{}