提交 c47cdc0d 编写于 作者: M Michael Woerister

Introduce HashStable trait and base ICH implementations on it.

This initial commit provides implementations for HIR, MIR, and
everything that also needs to be supported for those two.
上级 9e84bf80
......@@ -394,6 +394,10 @@ pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
}
}
pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
self.node_to_hir_id[node_id]
}
/// Add a definition with a parent definition.
pub fn create_def_with_parent(&mut self,
parent: Option<DefIndex>,
......
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use hir;
use hir::def_id::DefId;
use ich::{self, CachingCodemapView, DefPathHashes};
use session::config::DebugInfoLevel::NoDebugInfo;
use ty;
use std::hash as std_hash;
use syntax::ast;
use syntax::attr;
use syntax::ext::hygiene::SyntaxContext;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use rustc_data_structures::accumulate_vec::AccumulateVec;
/// This is the context state available during incr. comp. hashing. It contains
/// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
/// a reference to the TyCtxt) and it holds a few caches for speeding up various
/// things (e.g. each DefId/DefPath is only hashed once).
pub struct StableHashingContext<'a, 'tcx: 'a> {
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
def_path_hashes: DefPathHashes<'a, 'tcx>,
codemap: CachingCodemapView<'tcx>,
hash_spans: bool,
hash_bodies: bool,
overflow_checks_enabled: bool,
node_id_hashing_mode: NodeIdHashingMode,
// A sorted array of symbol keys for fast lookup.
ignored_attr_names: Vec<Symbol>,
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum NodeIdHashingMode {
Ignore,
HashDefPath,
HashTraitsInScope,
}
impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> {
pub fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Self {
let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo;
let check_overflow_initial = tcx.sess.overflow_checks();
let mut ignored_attr_names: Vec<_> = ich::IGNORED_ATTRIBUTES
.iter()
.map(|&s| Symbol::intern(s))
.collect();
ignored_attr_names.sort();
StableHashingContext {
tcx: tcx,
def_path_hashes: DefPathHashes::new(tcx),
codemap: CachingCodemapView::new(tcx),
hash_spans: hash_spans_initial,
hash_bodies: true,
overflow_checks_enabled: check_overflow_initial,
node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
ignored_attr_names: ignored_attr_names,
}
}
#[inline]
pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self,
hash_bodies: bool,
f: F) {
let prev_hash_bodies = self.hash_bodies;
self.hash_bodies = hash_bodies;
f(self);
self.hash_bodies = prev_hash_bodies;
}
#[inline]
pub fn while_hashing_spans<F: FnOnce(&mut Self)>(&mut self,
hash_spans: bool,
f: F) {
let prev_hash_spans = self.hash_spans;
self.hash_spans = hash_spans;
f(self);
self.hash_spans = prev_hash_spans;
}
#[inline]
pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>(&mut self,
mode: NodeIdHashingMode,
f: F) {
let prev = self.node_id_hashing_mode;
self.node_id_hashing_mode = mode;
f(self);
self.node_id_hashing_mode = prev;
}
#[inline]
pub fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}
#[inline]
pub fn def_path_hash(&mut self, def_id: DefId) -> u64 {
self.def_path_hashes.hash(def_id)
}
#[inline]
pub fn hash_spans(&self) -> bool {
self.hash_spans
}
#[inline]
pub fn hash_bodies(&self) -> bool {
self.hash_bodies
}
#[inline]
pub fn codemap(&mut self) -> &mut CachingCodemapView<'tcx> {
&mut self.codemap
}
#[inline]
pub fn is_ignored_attr(&self, name: Symbol) -> bool {
self.ignored_attr_names.binary_search(&name).is_ok()
}
pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self,
item_attrs: &[ast::Attribute],
f: F) {
let prev_overflow_checks = self.overflow_checks_enabled;
if attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") {
self.overflow_checks_enabled = true;
}
let prev_hash_node_ids = self.node_id_hashing_mode;
self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
f(self);
self.node_id_hashing_mode = prev_hash_node_ids;
self.overflow_checks_enabled = prev_overflow_checks;
}
#[inline]
pub fn binop_can_panic_at_runtime(&self, binop: hir::BinOp_) -> bool
{
match binop {
hir::BiAdd |
hir::BiSub |
hir::BiMul => self.overflow_checks_enabled,
hir::BiDiv |
hir::BiRem => true,
hir::BiAnd |
hir::BiOr |
hir::BiBitXor |
hir::BiBitAnd |
hir::BiBitOr |
hir::BiShl |
hir::BiShr |
hir::BiEq |
hir::BiLt |
hir::BiLe |
hir::BiNe |
hir::BiGe |
hir::BiGt => false
}
}
#[inline]
pub fn unop_can_panic_at_runtime(&self, unop: hir::UnOp) -> bool
{
match unop {
hir::UnDeref |
hir::UnNot => false,
hir::UnNeg => self.overflow_checks_enabled,
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::NodeId {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
match hcx.node_id_hashing_mode {
NodeIdHashingMode::Ignore => {
// Most NodeIds in the HIR can be ignored, but if there is a
// corresponding entry in the `trait_map` we need to hash that.
// Make sure we don't ignore too much by checking that there is
// no entry in a debug_assert!().
debug_assert!(hcx.tcx.trait_map.get(self).is_none());
}
NodeIdHashingMode::HashDefPath => {
hcx.tcx.hir.definitions().node_to_hir_id(*self).hash_stable(hcx, hasher);
}
NodeIdHashingMode::HashTraitsInScope => {
if let Some(traits) = hcx.tcx.trait_map.get(self) {
// The ordering of the candidates is not fixed. So we hash
// the def-ids and then sort them and hash the collection.
let mut candidates: AccumulateVec<[_; 8]> =
traits.iter()
.map(|&hir::TraitCandidate { def_id, import_id: _ }| {
hcx.def_path_hash(def_id)
})
.collect();
if traits.len() > 1 {
candidates.sort();
}
candidates.hash_stable(hcx, hasher);
}
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for Span {
// Hash a span in a stable way. We can't directly hash the span's BytePos
// fields (that would be similar to hashing pointers, since those are just
// offsets into the CodeMap). Instead, we hash the (file name, line, column)
// triple, which stays the same even if the containing FileMap has moved
// within the CodeMap.
// Also note that we are hashing byte offsets for the column, not unicode
// codepoint offsets. For the purpose of the hash that's sufficient.
// Also, hashing filenames is expensive so we avoid doing it twice when the
// span starts and ends in the same file, which is almost always the case.
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use syntax_pos::Pos;
if !hcx.hash_spans {
return
}
// If this is not an empty or invalid span, we want to hash the last
// position that belongs to it, as opposed to hashing the first
// position past it.
let span_hi = if self.hi > self.lo {
// We might end up in the middle of a multibyte character here,
// but that's OK, since we are not trying to decode anything at
// this position.
self.hi - ::syntax_pos::BytePos(1)
} else {
self.hi
};
{
let loc1 = hcx.codemap().byte_pos_to_line_and_col(self.lo);
let loc1 = loc1.as_ref()
.map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
.unwrap_or(("???", 0, 0));
let loc2 = hcx.codemap().byte_pos_to_line_and_col(span_hi);
let loc2 = loc2.as_ref()
.map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
.unwrap_or(("???", 0, 0));
if loc1.0 == loc2.0 {
std_hash::Hash::hash(&0u8, hasher);
std_hash::Hash::hash(loc1.0, hasher);
std_hash::Hash::hash(&loc1.1, hasher);
std_hash::Hash::hash(&loc1.2, hasher);
// Do not hash the file name twice
std_hash::Hash::hash(&loc2.1, hasher);
std_hash::Hash::hash(&loc2.2, hasher);
} else {
std_hash::Hash::hash(&1u8, hasher);
std_hash::Hash::hash(loc1.0, hasher);
std_hash::Hash::hash(&loc1.1, hasher);
std_hash::Hash::hash(&loc1.2, hasher);
std_hash::Hash::hash(loc2.0, hasher);
std_hash::Hash::hash(&loc2.1, hasher);
std_hash::Hash::hash(&loc2.2, hasher);
}
}
if self.ctxt == SyntaxContext::empty() {
0u8.hash_stable(hcx, hasher);
} else {
1u8.hash_stable(hcx, hasher);
self.source_callsite().hash_stable(hcx, hasher);
}
}
}
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `HashStable` implementations for various data types
//! from `rustc_const_math` in no particular order.
impl_stable_hash_for!(enum ::rustc_const_math::ConstFloat {
F32(val),
F64(val)
});
impl_stable_hash_for!(enum ::rustc_const_math::ConstInt {
I8(val),
I16(val),
I32(val),
I64(val),
I128(val),
Isize(val),
U8(val),
U16(val),
U32(val),
U64(val),
U128(val),
Usize(val)
});
impl_stable_hash_for!(enum ::rustc_const_math::ConstIsize {
Is16(i16),
Is32(i32),
Is64(i64)
});
impl_stable_hash_for!(enum ::rustc_const_math::ConstUsize {
Us16(i16),
Us32(i32),
Us64(i64)
});
impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr {
NotInRange,
CmpBetweenUnequalTypes,
UnequalTypes(op),
Overflow(op),
ShiftNegative,
DivisionByZero,
RemainderByZero,
UnsignedNegation,
ULitOutOfRange(int_ty),
LitOutOfRange(int_ty)
});
impl_stable_hash_for!(enum ::rustc_const_math::Op {
Add,
Sub,
Mul,
Div,
Rem,
Shr,
Shl,
Neg,
BitAnd,
BitOr,
BitXor
});
此差异已折叠。
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `HashStable` implementations for various MIR data
//! types in no particular order.
use ich::StableHashingContext;
use mir;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use std::mem;
impl_stable_hash_for!(struct mir::SourceInfo { span, scope });
impl_stable_hash_for!(enum mir::Mutability { Mut, Not });
impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut });
impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info });
impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
impl_stable_hash_for!(struct mir::Terminator<'tcx> { source_info, kind });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Local {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use rustc_data_structures::indexed_vec::Idx;
self.index().hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::BasicBlock {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use rustc_data_structures::indexed_vec::Idx;
self.index().hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Field {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use rustc_data_structures::indexed_vec::Idx;
self.index().hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::VisibilityScope {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use rustc_data_structures::indexed_vec::Idx;
self.index().hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Promoted {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use rustc_data_structures::indexed_vec::Idx;
self.index().hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::TerminatorKind<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::TerminatorKind::Goto { ref target } => {
target.hash_stable(hcx, hasher);
}
mir::TerminatorKind::SwitchInt { ref discr,
switch_ty,
ref values,
ref targets } => {
discr.hash_stable(hcx, hasher);
switch_ty.hash_stable(hcx, hasher);
values.hash_stable(hcx, hasher);
targets.hash_stable(hcx, hasher);
}
mir::TerminatorKind::Resume |
mir::TerminatorKind::Return |
mir::TerminatorKind::Unreachable => {}
mir::TerminatorKind::Drop { ref location, target, unwind } => {
location.hash_stable(hcx, hasher);
target.hash_stable(hcx, hasher);
unwind.hash_stable(hcx, hasher);
}
mir::TerminatorKind::DropAndReplace { ref location,
ref value,
target,
unwind, } => {
location.hash_stable(hcx, hasher);
value.hash_stable(hcx, hasher);
target.hash_stable(hcx, hasher);
unwind.hash_stable(hcx, hasher);
}
mir::TerminatorKind::Call { ref func,
ref args,
ref destination,
cleanup } => {
func.hash_stable(hcx, hasher);
args.hash_stable(hcx, hasher);
destination.hash_stable(hcx, hasher);
cleanup.hash_stable(hcx, hasher);
}
mir::TerminatorKind::Assert { ref cond,
expected,
ref msg,
target,
cleanup } => {
cond.hash_stable(hcx, hasher);
expected.hash_stable(hcx, hasher);
msg.hash_stable(hcx, hasher);
target.hash_stable(hcx, hasher);
cleanup.hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::AssertMessage<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::AssertMessage::BoundsCheck { ref len, ref index } => {
len.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
}
mir::AssertMessage::Math(ref const_math_err) => {
const_math_err.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::StatementKind<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
lvalue.hash_stable(hcx, hasher);
rvalue.hash_stable(hcx, hasher);
}
mir::StatementKind::SetDiscriminant { ref lvalue, variant_index } => {
lvalue.hash_stable(hcx, hasher);
variant_index.hash_stable(hcx, hasher);
}
mir::StatementKind::StorageLive(ref lvalue) |
mir::StatementKind::StorageDead(ref lvalue) => {
lvalue.hash_stable(hcx, hasher);
}
mir::StatementKind::Nop => {}
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
asm.hash_stable(hcx, hasher);
outputs.hash_stable(hcx, hasher);
inputs.hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Lvalue<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::Lvalue::Local(ref local) => {
local.hash_stable(hcx, hasher);
}
mir::Lvalue::Static(ref statik) => {
statik.hash_stable(hcx, hasher);
}
mir::Lvalue::Projection(ref lvalue_projection) => {
lvalue_projection.hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'tcx, B, V> HashStable<StableHashingContext<'a, 'tcx>> for mir::Projection<'tcx, B, V>
where B: HashStable<StableHashingContext<'a, 'tcx>>,
V: HashStable<StableHashingContext<'a, 'tcx>>
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let mir::Projection {
ref base,
ref elem,
} = *self;
base.hash_stable(hcx, hasher);
elem.hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx, V> HashStable<StableHashingContext<'a, 'tcx>> for mir::ProjectionElem<'tcx, V>
where V: HashStable<StableHashingContext<'a, 'tcx>>
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::ProjectionElem::Deref => {}
mir::ProjectionElem::Field(field, ty) => {
field.hash_stable(hcx, hasher);
ty.hash_stable(hcx, hasher);
}
mir::ProjectionElem::Index(ref value) => {
value.hash_stable(hcx, hasher);
}
mir::ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
offset.hash_stable(hcx, hasher);
min_length.hash_stable(hcx, hasher);
from_end.hash_stable(hcx, hasher);
}
mir::ProjectionElem::Subslice { from, to } => {
from.hash_stable(hcx, hasher);
to.hash_stable(hcx, hasher);
}
mir::ProjectionElem::Downcast(adt_def, variant) => {
adt_def.hash_stable(hcx, hasher);
variant.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Operand<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::Operand::Consume(ref lvalue) => {
lvalue.hash_stable(hcx, hasher);
}
mir::Operand::Constant(ref constant) => {
constant.hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Rvalue<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::Rvalue::Use(ref operand) => {
operand.hash_stable(hcx, hasher);
}
mir::Rvalue::Repeat(ref operand, ref val) => {
operand.hash_stable(hcx, hasher);
val.hash_stable(hcx, hasher);
}
mir::Rvalue::Ref(region, borrow_kind, ref lvalue) => {
region.hash_stable(hcx, hasher);
borrow_kind.hash_stable(hcx, hasher);
lvalue.hash_stable(hcx, hasher);
}
mir::Rvalue::Len(ref lvalue) => {
lvalue.hash_stable(hcx, hasher);
}
mir::Rvalue::Cast(cast_kind, ref operand, ty) => {
cast_kind.hash_stable(hcx, hasher);
operand.hash_stable(hcx, hasher);
ty.hash_stable(hcx, hasher);
}
mir::Rvalue::BinaryOp(op, ref operand1, ref operand2) |
mir::Rvalue::CheckedBinaryOp(op, ref operand1, ref operand2) => {
op.hash_stable(hcx, hasher);
operand1.hash_stable(hcx, hasher);
operand2.hash_stable(hcx, hasher);
}
mir::Rvalue::UnaryOp(op, ref operand) => {
op.hash_stable(hcx, hasher);
operand.hash_stable(hcx, hasher);
}
mir::Rvalue::Discriminant(ref lvalue) => {
lvalue.hash_stable(hcx, hasher);
}
mir::Rvalue::Box(ty) => {
ty.hash_stable(hcx, hasher);
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
kind.hash_stable(hcx, hasher);
operands.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(enum mir::CastKind {
Misc,
ReifyFnPointer,
ClosureFnPointer,
UnsafeFnPointer,
Unsize
});
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::AggregateKind<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::AggregateKind::Tuple => {}
mir::AggregateKind::Array(t) => {
t.hash_stable(hcx, hasher);
}
mir::AggregateKind::Adt(adt_def, idx, substs, active_field) => {
adt_def.hash_stable(hcx, hasher);
idx.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
active_field.hash_stable(hcx, hasher);
}
mir::AggregateKind::Closure(def_id, ref substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(enum mir::BinOp {
Add,
Sub,
Mul,
Div,
Rem,
BitXor,
BitAnd,
BitOr,
Shl,
Shr,
Eq,
Lt,
Le,
Ne,
Ge,
Gt
});
impl_stable_hash_for!(enum mir::UnOp {
Not,
Neg
});
impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Literal<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::Literal::Item { def_id, substs } => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
mir::Literal::Value { ref value } => {
value.hash_stable(hcx, hasher);
}
mir::Literal::Promoted { index } => {
index.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct mir::Location { block, statement_index });
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `HashStable` implementations for various data types
//! from libsyntax in no particular order.
use ich::StableHashingContext;
use std::hash as std_hash;
use std::mem;
use syntax::ast;
use syntax::parse::token;
use syntax::tokenstream;
use syntax_pos::Span;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use rustc_data_structures::accumulate_vec::AccumulateVec;
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::symbol::InternedString {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let s: &str = &**self;
s.hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Name {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
self.as_str().hash_stable(hcx, hasher);
}
}
impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
Att,
Intel
});
impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
Bang,
Attr,
Derive
});
impl_stable_hash_for!(enum ::syntax::abi::Abi {
Cdecl,
Stdcall,
Fastcall,
Vectorcall,
Aapcs,
Win64,
SysV64,
PtxKernel,
Msp430Interrupt,
X86Interrupt,
Rust,
C,
System,
RustIntrinsic,
RustCall,
PlatformIntrinsic,
Unadjusted
});
impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::attr::StabilityLevel {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
reason.hash_stable(hcx, hasher);
issue.hash_stable(hcx, hasher);
}
::syntax::attr::StabilityLevel::Stable { ref since } => {
since.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
impl_stable_hash_for!(enum ::syntax::attr::IntType {
SignedInt(int_ty),
UnsignedInt(uint_ty)
});
impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
Signed(int_ty),
Unsigned(int_ty),
Unsuffixed
});
impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
impl_stable_hash_for!(enum ::syntax::ast::LitKind {
Str(value, style),
ByteStr(value),
Byte(value),
Char(value),
Int(value, lit_int_type),
Float(value, float_ty),
FloatUnsuffixed(value),
Bool(value)
});
impl_stable_hash_for!(enum ::syntax::ast::IntTy { Is, I8, I16, I32, I64, I128 });
impl_stable_hash_for!(enum ::syntax::ast::UintTy { Us, U8, U16, U32, U64, U128 });
impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, name });
impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for [ast::Attribute] {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
// Some attributes are always ignored during hashing.
let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
.iter()
.filter(|attr| {
!attr.is_sugared_doc &&
attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
})
.collect();
filtered.len().hash_stable(hcx, hasher);
for attr in filtered {
attr.hash_stable(hcx, hasher);
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ast::Attribute {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
// Make sure that these have been filtered out.
debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
debug_assert!(!self.is_sugared_doc);
let ast::Attribute {
id: _,
style,
ref path,
ref tokens,
is_sugared_doc: _,
span,
} = *self;
style.hash_stable(hcx, hasher);
path.segments.len().hash_stable(hcx, hasher);
for segment in &path.segments {
segment.identifier.name.hash_stable(hcx, hasher);
}
for tt in tokens.trees() {
tt.hash_stable(hcx, hasher);
}
span.hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenTree {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
tokenstream::TokenTree::Token(span, ref token) => {
span.hash_stable(hcx, hasher);
hash_token(token, hcx, hasher, span);
}
tokenstream::TokenTree::Delimited(span, ref delimited) => {
span.hash_stable(hcx, hasher);
std_hash::Hash::hash(&delimited.delim, hasher);
for sub_tt in delimited.stream().trees() {
sub_tt.hash_stable(hcx, hasher);
}
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for tokenstream::TokenStream {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
for sub_tt in self.trees() {
sub_tt.hash_stable(hcx, hasher);
}
}
}
fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>,
error_reporting_span: Span) {
mem::discriminant(token).hash_stable(hcx, hasher);
match *token {
token::Token::Eq |
token::Token::Lt |
token::Token::Le |
token::Token::EqEq |
token::Token::Ne |
token::Token::Ge |
token::Token::Gt |
token::Token::AndAnd |
token::Token::OrOr |
token::Token::Not |
token::Token::Tilde |
token::Token::At |
token::Token::Dot |
token::Token::DotDot |
token::Token::DotDotDot |
token::Token::Comma |
token::Token::Semi |
token::Token::Colon |
token::Token::ModSep |
token::Token::RArrow |
token::Token::LArrow |
token::Token::FatArrow |
token::Token::Pound |
token::Token::Dollar |
token::Token::Question |
token::Token::Underscore |
token::Token::Whitespace |
token::Token::Comment |
token::Token::Eof => {}
token::Token::BinOp(bin_op_token) |
token::Token::BinOpEq(bin_op_token) => {
std_hash::Hash::hash(&bin_op_token, hasher);
}
token::Token::OpenDelim(delim_token) |
token::Token::CloseDelim(delim_token) => {
std_hash::Hash::hash(&delim_token, hasher);
}
token::Token::Literal(ref lit, ref opt_name) => {
mem::discriminant(lit).hash_stable(hcx, hasher);
match *lit {
token::Lit::Byte(val) |
token::Lit::Char(val) |
token::Lit::Integer(val) |
token::Lit::Float(val) |
token::Lit::Str_(val) |
token::Lit::ByteStr(val) => val.hash_stable(hcx, hasher),
token::Lit::StrRaw(val, n) |
token::Lit::ByteStrRaw(val, n) => {
val.hash_stable(hcx, hasher);
n.hash_stable(hcx, hasher);
}
};
opt_name.hash_stable(hcx, hasher);
}
token::Token::Ident(ident) |
token::Token::Lifetime(ident) |
token::Token::SubstNt(ident) => ident.name.hash_stable(hcx, hasher),
token::Token::Interpolated(ref non_terminal) => {
// FIXME(mw): This could be implemented properly. It's just a
// lot of work, since we would need to hash the AST
// in a stable way, in addition to the HIR.
// Since this is hardly used anywhere, just emit a
// warning for now.
if hcx.tcx().sess.opts.debugging_opts.incremental.is_some() {
let msg = format!("Quasi-quoting might make incremental \
compilation very inefficient: {:?}",
non_terminal);
hcx.tcx().sess.span_warn(error_reporting_span, &msg[..]);
}
std_hash::Hash::hash(non_terminal, hasher);
}
token::Token::DocComment(val) |
token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
}
}
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `HashStable` implementations for various data types
//! from rustc::ty in no particular order.
use ich::StableHashingContext;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use std::hash as std_hash;
use std::mem;
use ty;
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Ty<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let type_hash = hcx.tcx().type_id_hash(*self);
type_hash.hash_stable(hcx, hasher);
}
}
impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Slice<T>
where T: HashStable<StableHashingContext<'a, 'tcx>> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
(&**self).hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::subst::Kind<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
self.as_type().hash_stable(hcx, hasher);
self.as_region().hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Region {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::ReErased |
ty::ReStatic |
ty::ReEmpty => {
// No variant fields to hash for these ...
}
ty::ReLateBound(db, ty::BrAnon(i)) => {
db.depth.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);
}
ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
index.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
ty::ReLateBound(..) |
ty::ReFree(..) |
ty::ReScope(..) |
ty::ReVar(..) |
ty::ReSkolemized(..) => {
bug!("TypeIdHasher: unexpected region {:?}", *self)
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::AutoBorrow<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::adjustment::AutoBorrow::Ref(ref region, mutability) => {
region.hash_stable(hcx, hasher);
mutability.hash_stable(hcx, hasher);
}
ty::adjustment::AutoBorrow::RawPtr(mutability) => {
mutability.hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::Adjust<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::adjustment::Adjust::NeverToAny |
ty::adjustment::Adjust::ReifyFnPointer |
ty::adjustment::Adjust::UnsafeFnPointer |
ty::adjustment::Adjust::ClosureFnPointer |
ty::adjustment::Adjust::MutToConstPointer => {}
ty::adjustment::Adjust::DerefRef { autoderefs, ref autoref, unsize } => {
autoderefs.hash_stable(hcx, hasher);
autoref.hash_stable(hcx, hasher);
unsize.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
impl_stable_hash_for!(struct ty::MethodCall { expr_id, autoderef });
impl_stable_hash_for!(struct ty::MethodCallee<'tcx> { def_id, ty, substs });
impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
impl_stable_hash_for!(enum ty::BorrowKind {
ImmBorrow,
UniqueImmBorrow,
MutBorrow
});
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::UpvarCapture::ByValue => {}
ty::UpvarCapture::ByRef(ref up_var_borrow) => {
up_var_borrow.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct ty::FnSig<'tcx> {
inputs_and_output,
variadic,
unsafety,
abi
});
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Binder<T>
where T: HashStable<StableHashingContext<'a, 'tcx>> + ty::fold::TypeFoldable<'tcx>
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
hcx.tcx().anonymize_late_bound_regions(self).0.hash_stable(hcx, hasher);
}
}
impl_stable_hash_for!(enum ty::ClosureKind { Fn, FnMut, FnOnce });
impl_stable_hash_for!(enum ty::Visibility {
Public,
Restricted(def_id),
Invisible
});
impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
impl<'a, 'tcx, A, B> HashStable<StableHashingContext<'a, 'tcx>> for ty::OutlivesPredicate<A, B>
where A: HashStable<StableHashingContext<'a, 'tcx>>,
B: HashStable<StableHashingContext<'a, 'tcx>>,
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let ty::OutlivesPredicate(ref a, ref b) = *self;
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher);
}
}
impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty });
impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_name });
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Predicate<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::Predicate::Trait(ref pred) => {
pred.hash_stable(hcx, hasher);
}
ty::Predicate::Equate(ref pred) => {
pred.hash_stable(hcx, hasher);
}
ty::Predicate::RegionOutlives(ref pred) => {
pred.hash_stable(hcx, hasher);
}
ty::Predicate::TypeOutlives(ref pred) => {
pred.hash_stable(hcx, hasher);
}
ty::Predicate::Projection(ref pred) => {
pred.hash_stable(hcx, hasher);
}
ty::Predicate::WellFormed(ty) => {
ty.hash_stable(hcx, hasher);
}
ty::Predicate::ObjectSafe(def_id) => {
def_id.hash_stable(hcx, hasher);
}
ty::Predicate::ClosureKind(def_id, closure_kind) => {
def_id.hash_stable(hcx, hasher);
closure_kind.hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
fn hash_stable<W: StableHasherResult>(&self,
_: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
std_hash::Hash::hash(self, hasher);
}
}
impl_stable_hash_for!(struct ty::VariantDef {
did,
name,
discr,
fields,
ctor_kind
});
impl_stable_hash_for!(enum ty::VariantDiscr {
Explicit(def_id),
Relative(distance)
});
impl_stable_hash_for!(struct ty::FieldDef {
did,
name,
vis
});
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>>
for ::middle::const_val::ConstVal<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use middle::const_val::ConstVal;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ConstVal::Float(ref value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::Integral(ref value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::Str(ref value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::ByteStr(ref value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::Bool(value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::Function(def_id, substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
ConstVal::Struct(ref _name_value_map) => {
// BTreeMap<ast::Name, ConstVal<'tcx>>),
panic!("Ordering still unstable")
}
ConstVal::Tuple(ref value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::Array(ref value) => {
value.hash_stable(hcx, hasher);
}
ConstVal::Repeat(ref value, times) => {
value.hash_stable(hcx, hasher);
times.hash_stable(hcx, hasher);
}
ConstVal::Char(value) => {
value.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
parent,
predicates
});
impl_stable_hash_for!(enum ty::Variance {
Covariant,
Invariant,
Contravariant,
Bivariant
});
impl_stable_hash_for!(enum ty::adjustment::CustomCoerceUnsized {
Struct(index)
});
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Generics {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let ty::Generics {
parent,
parent_regions,
parent_types,
ref regions,
ref types,
// Reverse map to each `TypeParameterDef`'s `index` field, from
// `def_id.index` (`def_id.krate` is the same as the item's).
type_param_to_index: _, // Don't hash this
has_self,
} = *self;
parent.hash_stable(hcx, hasher);
parent_regions.hash_stable(hcx, hasher);
parent_types.hash_stable(hcx, hasher);
regions.hash_stable(hcx, hasher);
types.hash_stable(hcx, hasher);
has_self.hash_stable(hcx, hasher);
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionParameterDef {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let ty::RegionParameterDef {
name,
def_id,
index,
issue_32330: _,
pure_wrt_drop
} = *self;
name.hash_stable(hcx, hasher);
def_id.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
pure_wrt_drop.hash_stable(hcx, hasher);
}
}
impl_stable_hash_for!(struct ty::TypeParameterDef {
name,
def_id,
index,
has_default,
object_lifetime_default,
pure_wrt_drop
});
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>>
for ::middle::resolve_lifetime::Set1<T>
where T: HashStable<StableHashingContext<'a, 'tcx>>
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
use middle::resolve_lifetime::Set1;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
Set1::Empty |
Set1::Many => {
// Nothing to do.
}
Set1::One(ref value) => {
value.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
Static,
EarlyBound(index, decl),
LateBound(db_index, decl),
LateBoundAnon(db_index, anon_index),
Free(call_site_scope_data, decl)
});
impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
fn_id,
body_id
});
impl_stable_hash_for!(struct ty::DebruijnIndex {
depth
});
......@@ -8,13 +8,23 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! ICH - Incremental Compilation Hash
pub use self::fingerprint::Fingerprint;
pub use self::def_path_hash::DefPathHashes;
pub use self::caching_codemap_view::CachingCodemapView;
pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
mod fingerprint;
mod def_path_hash;
mod caching_codemap_view;
mod hcx;
mod impls_const_math;
mod impls_hir;
mod impls_mir;
mod impls_ty;
mod impls_syntax;
pub const ATTR_DIRTY: &'static str = "rustc_dirty";
pub const ATTR_CLEAN: &'static str = "rustc_clean";
......@@ -22,6 +32,20 @@
pub const ATTR_CLEAN_METADATA: &'static str = "rustc_metadata_clean";
pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
pub const ATTR_PARTITION_REUSED: &'static str = "rustc_partition_reused";
pub const ATTR_PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
pub const DEP_GRAPH_ASSERT_ATTRS: &'static [&'static str] = &[
ATTR_IF_THIS_CHANGED,
ATTR_THEN_THIS_WOULD_NEED,
ATTR_DIRTY,
ATTR_CLEAN,
ATTR_DIRTY_METADATA,
ATTR_CLEAN_METADATA,
ATTR_PARTITION_REUSED,
ATTR_PARTITION_TRANSLATED,
];
pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
"cfg",
......@@ -30,5 +54,7 @@
ATTR_DIRTY,
ATTR_CLEAN,
ATTR_DIRTY_METADATA,
ATTR_CLEAN_METADATA
ATTR_CLEAN_METADATA,
ATTR_PARTITION_REUSED,
ATTR_PARTITION_TRANSLATED,
];
......@@ -41,6 +41,7 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(discriminant_value)]
extern crate arena;
extern crate core;
......
......@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
macro_rules! enum_from_u32 {
($(#[$attr:meta])* pub enum $name:ident {
$($variant:ident = $e:expr,)*
......@@ -59,3 +61,80 @@ pub fn from_u32(u: u32) -> Option<$name> {
$crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*))
})
}
#[macro_export]
macro_rules! __impl_stable_hash_field {
(DECL IGNORED) => (_);
(DECL $name:ident) => (ref $name);
(USE IGNORED $ctx:expr, $hasher:expr) => ({});
(USE $name:ident, $ctx:expr, $hasher:expr) => ($name.hash_stable($ctx, $hasher));
}
#[macro_export]
macro_rules! impl_stable_hash_for {
(enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $enum_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
__ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>,
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
use $enum_name::*;
::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
match *self {
$(
$variant $( ( $( __impl_stable_hash_field!(DECL $arg) ),* ) )* => {
$($( __impl_stable_hash_field!(USE $arg, __ctx, __hasher) );*)*
}
)*
}
}
}
};
(struct $struct_name:path { $($field:ident),* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
__ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>,
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
let $struct_name {
$(ref $field),*
} = *self;
$( $field.hash_stable(__ctx, __hasher));*
}
}
};
(tuple_struct $struct_name:path { $($field:ident),* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
__ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>,
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
let $struct_name (
$(ref $field),*
) = *self;
$( $field.hash_stable(__ctx, __hasher));*
}
}
};
}
#[macro_export]
macro_rules! impl_stable_hash_for_spanned {
($T:path) => (
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::syntax::codemap::Spanned<$T>
{
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
self.node.hash_stable(hcx, hasher);
self.span.hash_stable(hcx, hasher);
}
}
);
}
......@@ -10,7 +10,9 @@
use std::cell::{Ref, RefCell};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use ich::StableHashingContext;
use mir::{Mir, BasicBlock};
use rustc_serialize as serialize;
......@@ -33,6 +35,13 @@ fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for Cache {
fn hash_stable<W: StableHasherResult>(&self,
_: &mut StableHashingContext<'a, 'tcx>,
_: &mut StableHasher<W>) {
// do nothing
}
}
impl Cache {
pub fn new() -> Self {
......
......@@ -243,6 +243,19 @@ pub fn make_statement_nop(&mut self, location: Location) {
}
}
impl_stable_hash_for!(struct Mir<'tcx> {
basic_blocks,
visibility_scopes,
promoted,
return_ty,
local_decls,
arg_count,
upvar_decls,
spread_arg,
span,
cache
});
impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
type Output = BasicBlockData<'tcx>;
......@@ -830,6 +843,11 @@ pub struct Static<'tcx> {
pub ty: Ty<'tcx>,
}
impl_stable_hash_for!(struct Static<'tcx> {
def_id,
ty
});
/// The `Projection` data structure defines things of the form `B.x`
/// or `*B` or `B[index]`. Note that it is parameterized because it is
/// shared between `Constant` and `Lvalue`. See the aliases
......
......@@ -19,6 +19,7 @@
use hir::{map as hir_map, FreevarMap, TraitMap};
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use ich::StableHashingContext;
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
......@@ -50,6 +51,8 @@
use rustc_const_math::ConstInt;
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
use hir;
use hir::itemlikevisit::ItemLikeVisitor;
......@@ -1379,6 +1382,25 @@ fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for AdtDef {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
let ty::AdtDef {
did,
ref variants,
ref flags,
ref repr,
} = *self;
did.hash_stable(hcx, hasher);
variants.hash_stable(hcx, hasher);
flags.hash_stable(hcx, hasher);
repr.hash_stable(hcx, hasher);
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Union, Enum }
......@@ -1391,6 +1413,13 @@ pub struct ReprOptions {
pub int: Option<attr::IntType>,
}
impl_stable_hash_for!(struct ReprOptions {
c,
packed,
simd,
int
});
impl ReprOptions {
pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
let mut ret = ReprOptions::default();
......
......@@ -37,6 +37,8 @@
#![feature(unsize)]
#![feature(i128_type)]
#![feature(conservative_impl_trait)]
#![feature(discriminant_value)]
#![feature(specialization)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::hash::Hasher;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use blake2b::Blake2bHasher;
......@@ -174,3 +174,193 @@ fn write_isize(&mut self, i: isize) {
self.write_ileb128(i as i64);
}
}
/// Something that implements `HashStable<CTX>` can be hashed in a way that is
/// stable across multiple compiliation sessions.
pub trait HashStable<CTX> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut CTX,
hasher: &mut StableHasher<W>);
}
// Implement HashStable by just calling `Hash::hash()`. This works fine for
// self-contained values that don't depend on the hashing context `CTX`.
macro_rules! impl_stable_hash_via_hash {
($t:ty) => (
impl<CTX> HashStable<CTX> for $t {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
_: &mut CTX,
hasher: &mut StableHasher<W>) {
::std::hash::Hash::hash(self, hasher);
}
}
);
}
impl_stable_hash_via_hash!(i8);
impl_stable_hash_via_hash!(i16);
impl_stable_hash_via_hash!(i32);
impl_stable_hash_via_hash!(i64);
impl_stable_hash_via_hash!(isize);
impl_stable_hash_via_hash!(u8);
impl_stable_hash_via_hash!(u16);
impl_stable_hash_via_hash!(u32);
impl_stable_hash_via_hash!(u64);
impl_stable_hash_via_hash!(usize);
impl_stable_hash_via_hash!(u128);
impl_stable_hash_via_hash!(i128);
impl_stable_hash_via_hash!(char);
impl_stable_hash_via_hash!(());
impl<CTX> HashStable<CTX> for f32 {
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
let val: u32 = unsafe {
::std::mem::transmute(*self)
};
val.hash_stable(ctx, hasher);
}
}
impl<CTX> HashStable<CTX> for f64 {
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
let val: u64 = unsafe {
::std::mem::transmute(*self)
};
val.hash_stable(ctx, hasher);
}
}
impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2) {
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
self.0.hash_stable(ctx, hasher);
self.1.hash_stable(ctx, hasher);
}
}
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
default fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
self.len().hash_stable(ctx, hasher);
for item in self {
item.hash_stable(ctx, hasher);
}
}
}
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
(&self[..]).hash_stable(ctx, hasher);
}
}
impl<CTX> HashStable<CTX> for str {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
_: &mut CTX,
hasher: &mut StableHasher<W>) {
self.len().hash(hasher);
self.as_bytes().hash(hasher);
}
}
impl<CTX> HashStable<CTX> for bool {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
(if *self { 1u8 } else { 0u8 }).hash_stable(ctx, hasher);
}
}
impl<T, CTX> HashStable<CTX> for Option<T>
where T: HashStable<CTX>
{
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
if let Some(ref value) = *self {
1u8.hash_stable(ctx, hasher);
value.hash_stable(ctx, hasher);
} else {
0u8.hash_stable(ctx, hasher);
}
}
}
impl<'a, T, CTX> HashStable<CTX> for &'a T
where T: HashStable<CTX>
{
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
(**self).hash_stable(ctx, hasher);
}
}
impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
_: &mut CTX,
hasher: &mut StableHasher<W>) {
::std::hash::Hash::hash(self, hasher);
}
}
impl<K, V, CTX> HashStable<CTX> for ::std::collections::BTreeMap<K, V>
where K: Ord + HashStable<CTX>,
V: HashStable<CTX>,
{
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
self.len().hash_stable(ctx, hasher);
for (k, v) in self {
k.hash_stable(ctx, hasher);
v.hash_stable(ctx, hasher);
}
}
}
impl<T, CTX> HashStable<CTX> for ::std::collections::BTreeSet<T>
where T: Ord + HashStable<CTX>,
{
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
self.len().hash_stable(ctx, hasher);
for v in self {
v.hash_stable(ctx, hasher);
}
}
}
impl<I: ::indexed_vec::Idx, T, CTX> HashStable<CTX> for ::indexed_vec::IndexVec<I, T>
where T: HashStable<CTX>,
{
fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX,
hasher: &mut StableHasher<W>) {
self.len().hash_stable(ctx, hasher);
for v in &self.raw {
v.hash_stable(ctx, hasher);
}
}
}
......@@ -27,24 +27,17 @@
//! at the end of compilation would be different from those computed
//! at the beginning.
use syntax::ast;
use std::cell::RefCell;
use std::hash::Hash;
use rustc::dep_graph::DepNode;
use rustc::hir;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::intravisit as visit;
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
use rustc::ich::{Fingerprint, DefPathHashes, CachingCodemapView};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ich::{Fingerprint, StableHashingContext};
use rustc::ty::TyCtxt;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
use rustc_data_structures::fx::FxHashMap;
use rustc::util::common::record_time;
use rustc::session::config::DebugInfoLevel::NoDebugInfo;
use self::svh_visitor::StrictVersionHashVisitor;
mod svh_visitor;
pub type IchHasher = StableHasher<Fingerprint>;
......@@ -94,91 +87,42 @@ fn index(&self, index: &'a DepNode<DefId>) -> &Fingerprint {
}
}
pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> IncrementalHashesMap {
let _ignore = tcx.dep_graph.in_ignore();
let krate = tcx.hir.krate();
let hash_spans = tcx.sess.opts.debuginfo != NoDebugInfo;
let mut visitor = HashItemsVisitor {
tcx: tcx,
hashes: IncrementalHashesMap::new(),
def_path_hashes: DefPathHashes::new(tcx),
codemap: CachingCodemapView::new(tcx),
hash_spans: hash_spans,
};
record_time(&tcx.sess.perf_stats.incr_comp_hashes_time, || {
visitor.calculate_def_id(DefId::local(CRATE_DEF_INDEX), |v| {
v.hash_crate_root_module(krate);
});
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
for macro_def in krate.exported_macros.iter() {
visitor.calculate_node_id(macro_def.id,
|v| v.visit_macro_def(macro_def));
}
});
tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash());
visitor.hashes
}
struct HashItemsVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_path_hashes: DefPathHashes<'a, 'tcx>,
codemap: CachingCodemapView<'tcx>,
struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
hcx: StableHashingContext<'a, 'tcx>,
hashes: IncrementalHashesMap,
hash_spans: bool,
}
impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> {
fn calculate_node_id<W>(&mut self, id: ast::NodeId, walk_op: W)
where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
{
let def_id = self.tcx.hir.local_def_id(id);
self.calculate_def_id(def_id, walk_op)
}
fn calculate_def_id<W>(&mut self, def_id: DefId, mut walk_op: W)
where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
fn compute_and_store_ich_for_item_like<T>(&mut self,
dep_node: DepNode<DefId>,
hash_bodies: bool,
item_like: T)
where T: HashStable<StableHashingContext<'a, 'tcx>>
{
assert!(def_id.is_local());
debug!("HashItemsVisitor::calculate(def_id={:?})", def_id);
self.calculate_def_hash(DepNode::Hir(def_id), false, &mut walk_op);
self.calculate_def_hash(DepNode::HirBody(def_id), true, &mut walk_op);
}
let mut hasher = IchHasher::new();
self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| {
item_like.hash_stable(hcx, &mut hasher);
});
fn calculate_def_hash<W>(&mut self,
dep_node: DepNode<DefId>,
hash_bodies: bool,
walk_op: &mut W)
where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
{
let mut state = IchHasher::new();
walk_op(&mut StrictVersionHashVisitor::new(&mut state,
self.tcx,
&mut self.def_path_hashes,
&mut self.codemap,
self.hash_spans,
hash_bodies));
let bytes_hashed = state.bytes_hashed();
let item_hash = state.finish();
let bytes_hashed = hasher.bytes_hashed();
let item_hash = hasher.finish();
debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
self.hashes.insert(dep_node, item_hash);
let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
let tcx = self.hcx.tcx();
let bytes_hashed =
tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
bytes_hashed;
self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
}
fn compute_crate_hash(&mut self) {
let krate = self.tcx.hir.krate();
let tcx = self.hcx.tcx();
let krate = tcx.hir.krate();
let mut crate_state = IchHasher::new();
let crate_disambiguator = self.tcx.sess.local_crate_disambiguator();
let crate_disambiguator = tcx.sess.local_crate_disambiguator();
"crate_disambiguator".hash(&mut crate_state);
crate_disambiguator.as_str().len().hash(&mut crate_state);
crate_disambiguator.as_str().hash(&mut crate_state);
......@@ -186,7 +130,7 @@ fn compute_crate_hash(&mut self) {
// add each item (in some deterministic order) to the overall
// crate hash.
{
let def_path_hashes = &mut self.def_path_hashes;
let hcx = &mut self.hcx;
let mut item_hashes: Vec<_> =
self.hashes.iter()
.map(|(item_dep_node, &item_hash)| {
......@@ -194,7 +138,7 @@ fn compute_crate_hash(&mut self) {
// DepNode<u64> where the u64 is the
// hash of the def-id's def-path:
let item_dep_node =
item_dep_node.map_def(|&did| Some(def_path_hashes.hash(did)))
item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did)))
.unwrap();
(item_dep_node, item_hash)
})
......@@ -203,40 +147,85 @@ fn compute_crate_hash(&mut self) {
item_hashes.hash(&mut crate_state);
}
{
let mut visitor = StrictVersionHashVisitor::new(&mut crate_state,
self.tcx,
&mut self.def_path_hashes,
&mut self.codemap,
self.hash_spans,
false);
visitor.hash_attributes(&krate.attrs);
}
krate.attrs.hash_stable(&mut self.hcx, &mut crate_state);
let crate_hash = crate_state.finish();
self.hashes.insert(DepNode::Krate, crate_hash);
debug!("calculate_crate_hash: crate_hash={:?}", crate_hash);
}
}
impl<'a, 'tcx> Visitor<'tcx> for HashItemsVisitor<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
fn hash_crate_root_module(&mut self, krate: &'tcx hir::Crate) {
let hir::Crate {
ref module,
// Crate attributes are not copied over to the root `Mod`, so hash
// them explicitly here.
ref attrs,
span,
// These fields are handled separately:
exported_macros: _,
items: _,
trait_items: _,
impl_items: _,
bodies: _,
trait_impls: _,
trait_default_impl: _,
body_ids: _,
} = *krate;
let def_id = DefId::local(CRATE_DEF_INDEX);
self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id),
false,
(module, (span, attrs)));
self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id),
true,
(module, (span, attrs)));
}
}
impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
self.calculate_node_id(item.id, |v| v.visit_item(item));
visit::walk_item(self, item);
let def_id = self.hcx.tcx().hir.local_def_id(item.id);
self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item);
self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
self.calculate_node_id(trait_item.id, |v| v.visit_trait_item(trait_item));
visit::walk_trait_item(self, trait_item);
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
let def_id = self.hcx.tcx().hir.local_def_id(item.id);
self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item);
self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
self.calculate_node_id(impl_item.id, |v| v.visit_impl_item(impl_item));
visit::walk_impl_item(self, impl_item);
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
let def_id = self.hcx.tcx().hir.local_def_id(item.id);
self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item);
self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item);
}
}
pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> IncrementalHashesMap {
let _ignore = tcx.dep_graph.in_ignore();
let krate = tcx.hir.krate();
let mut visitor = ComputeItemHashesVisitor {
hcx: StableHashingContext::new(tcx),
hashes: IncrementalHashesMap::new(),
};
record_time(&tcx.sess.perf_stats.incr_comp_hashes_time, || {
visitor.hash_crate_root_module(krate);
krate.visit_all_item_likes(&mut visitor);
for macro_def in krate.exported_macros.iter() {
let def_id = tcx.hir.local_def_id(macro_def.id);
visitor.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, macro_def);
visitor.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, macro_def);
}
});
tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash());
visitor.hashes
}
......@@ -22,7 +22,6 @@
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(rand)]
#![feature(core_intrinsics)]
#![feature(conservative_impl_trait)]
#![cfg_attr(stage0, feature(pub_restricted))]
......
......@@ -32,8 +32,7 @@
use {ModuleSource, ModuleTranslation};
const PARTITION_REUSED: &'static str = "rustc_partition_reused";
const PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
const MODULE: &'static str = "module";
const CFG: &'static str = "cfg";
......@@ -62,9 +61,9 @@ struct AssertModuleSource<'a, 'tcx: 'a> {
impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
fn check_attr(&self, attr: &ast::Attribute) {
let disposition = if attr.check_name(PARTITION_REUSED) {
let disposition = if attr.check_name(ATTR_PARTITION_REUSED) {
Disposition::Reused
} else if attr.check_name(PARTITION_TRANSLATED) {
} else if attr.check_name(ATTR_PARTITION_TRANSLATED) {
Disposition::Translated
} else {
return;
......
......@@ -43,6 +43,8 @@
use serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
/// An owned smart pointer.
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct P<T: ?Sized> {
......@@ -215,3 +217,13 @@ fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
}))
}
}
impl<CTX, T> HashStable<CTX> for P<T>
where T: ?Sized + HashStable<CTX>
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut CTX,
hasher: &mut StableHasher<W>) {
(**self).hash_stable(hcx, hasher);
}
}
......@@ -12,6 +12,9 @@
use std::ops::Deref;
use std::rc::Rc;
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
#[derive(Clone)]
pub struct RcSlice<T> {
data: Rc<Box<[T]>>,
......@@ -41,3 +44,13 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}
impl<CTX, T> HashStable<CTX> for RcSlice<T>
where T: HashStable<CTX>
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut CTX,
hasher: &mut StableHasher<W>) {
(**self).hash_stable(hcx, hasher);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册