Fix issues uncovered by rebasing:

- Don't hash traits in scope as part of HIR hashing any more.
- Some queries returned DefIndexes from other crates.
- Provide a generic way of stably hashing maps (not used everywhere yet).
This commit is contained in:
Michael Woerister 2017-09-12 17:07:09 +02:00
parent 3cc3ae22bd
commit e3f913167c
22 changed files with 342 additions and 251 deletions

View File

@ -633,6 +633,18 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
}
}
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIndex,) {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
tcx.hir.definitions().def_path_hash(self.0).0
}
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
tcx.item_path_str(DefId::local(self.0))
}
}
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) {
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;

View File

@ -27,7 +27,8 @@ use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvider,
StableHasher, StableHasherResult};
StableHasher, StableHasherResult,
ToStableHashKey};
use rustc_data_structures::accumulate_vec::AccumulateVec;
/// This is the context state available during incr. comp. hashing. It contains
@ -48,9 +49,7 @@ pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum NodeIdHashingMode {
Ignore,
CheckedIgnore,
HashDefPath,
HashTraitsInScope,
}
impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
@ -150,7 +149,7 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
self.overflow_checks_enabled = true;
}
let prev_hash_node_ids = self.node_id_hashing_mode;
self.node_id_hashing_mode = NodeIdHashingMode::CheckedIgnore;
self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
f(self);
@ -207,41 +206,28 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::N
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) {
let hir_id = hcx.tcx.hir.node_to_hir_id(*self);
match hcx.node_id_hashing_mode {
NodeIdHashingMode::Ignore => {
// Don't do anything.
}
NodeIdHashingMode::CheckedIgnore => {
// 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.in_scope_traits(hir_id).is_none());
}
NodeIdHashingMode::HashDefPath => {
hir_id.hash_stable(hcx, hasher);
}
NodeIdHashingMode::HashTraitsInScope => {
if let Some(traits) = hcx.tcx.in_scope_traits(hir_id) {
// 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);
}
hcx.tcx.hir.node_to_hir_id(*self).hash_stable(hcx, hasher);
}
}
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
type KeyType = (DefPathHash, hir::ItemLocalId);
#[inline]
fn to_stable_hash_key(&self,
hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
-> (DefPathHash, hir::ItemLocalId) {
hcx.tcx.hir.node_to_hir_id(*self).to_stable_hash_key(hcx)
}
}
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
// Hash a span in a stable way. We can't directly hash the span's BytePos

View File

@ -45,3 +45,9 @@ impl_stable_hash_for!(struct middle::cstore::ExternCrate {
direct,
path_len
});
impl_stable_hash_for!(struct middle::cstore::CrateSource {
dylib,
rlib,
rmeta
});

View File

@ -12,13 +12,13 @@
//! types in no particular order.
use hir;
use hir::map::DefPathHash;
use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
use ich::{self, StableHashingContext, NodeIdHashingMode};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use ich::{StableHashingContext, NodeIdHashingMode};
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
StableHasher, StableHasherResult};
use std::mem;
use syntax::ast;
use util::nodemap::DefIdSet;
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
#[inline]
@ -29,14 +29,12 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefId
}
}
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for DefIdSet
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) {
ich::hash_stable_hashset(hcx, hasher, self, |hcx, def_id| {
hcx.def_path_hash(*def_id)
});
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for DefId {
type KeyType = DefPathHash;
#[inline]
fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
hcx.tcx().def_path_hash(*self)
}
}
@ -50,11 +48,22 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::H
local_id,
} = *self;
hcx.def_path_hash(DefId::local(owner)).hash_stable(hcx, hasher);
hcx.tcx().hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
local_id.hash_stable(hcx, hasher);
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
type KeyType = (DefPathHash, hir::ItemLocalId);
#[inline]
fn to_stable_hash_key(&self,
hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
-> (DefPathHash, hir::ItemLocalId) {
let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
(def_path_hash, self.local_id)
}
}
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
#[inline]
@ -68,8 +77,30 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateN
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
type KeyType = DefPathHash;
#[inline]
fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
def_id.to_stable_hash_key(hcx)
}
}
impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
impl<'a, 'gcx, 'lcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'lcx>>
for hir::ItemLocalId {
type KeyType = hir::ItemLocalId;
#[inline]
fn to_stable_hash_key(&self,
_: &StableHashingContext<'a, 'gcx, 'lcx>)
-> hir::ItemLocalId {
*self
}
}
// The following implementations of HashStable for ItemId, TraitItemId, and
// ImplItemId deserve special attention. Normally we do not hash NodeIds within
// the HIR, since they just signify a HIR nodes own path. But ItemId et al
@ -231,36 +262,13 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) {
let node_id_hashing_mode = match self.node {
hir::TySlice(..) |
hir::TyArray(..) |
hir::TyPtr(..) |
hir::TyRptr(..) |
hir::TyBareFn(..) |
hir::TyNever |
hir::TyTup(..) |
hir::TyTraitObject(..) |
hir::TyImplTrait(..) |
hir::TyTypeof(..) |
hir::TyErr |
hir::TyInfer => {
NodeIdHashingMode::CheckedIgnore
}
hir::TyPath(..) => {
NodeIdHashingMode::HashTraitsInScope
}
};
hcx.while_hashing_hir_bodies(true, |hcx| {
let hir::Ty {
id,
id: _,
ref node,
ref span,
} = *self;
hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
id.hash_stable(hcx, hasher);
});
node.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
})
@ -317,13 +325,11 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
hasher: &mut StableHasher<W>) {
let hir::TraitRef {
ref path,
ref_id,
// Don't hash the ref_id. It is tracked via the thing it is used to access
ref_id: _,
} = *self;
path.hash_stable(hcx, hasher);
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
ref_id.hash_stable(hcx, hasher);
});
}
}
@ -357,7 +363,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
let hir::Block {
ref stmts,
ref expr,
id,
id: _,
hir_id: _,
rules,
span,
@ -392,7 +398,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
}
expr.hash_stable(hcx, hasher);
id.hash_stable(hcx, hasher);
rules.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
targeted_by_break.hash_stable(hcx, hasher);
@ -403,34 +408,13 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::P
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) {
let node_id_hashing_mode = match self.node {
hir::PatKind::Wild |
hir::PatKind::Binding(..) |
hir::PatKind::Tuple(..) |
hir::PatKind::Box(..) |
hir::PatKind::Ref(..) |
hir::PatKind::Lit(..) |
hir::PatKind::Range(..) |
hir::PatKind::Slice(..) => {
NodeIdHashingMode::CheckedIgnore
}
hir::PatKind::Path(..) |
hir::PatKind::Struct(..) |
hir::PatKind::TupleStruct(..) => {
NodeIdHashingMode::HashTraitsInScope
}
};
let hir::Pat {
id,
id: _,
hir_id: _,
ref node,
ref span
} = *self;
hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
id.hash_stable(hcx, hasher);
});
node.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
}
@ -552,14 +536,14 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::E
hasher: &mut StableHasher<W>) {
hcx.while_hashing_hir_bodies(true, |hcx| {
let hir::Expr {
id,
id: _,
hir_id: _,
ref span,
ref node,
ref attrs
} = *self;
let (spans_always_on, node_id_hashing_mode) = match *node {
let spans_always_on = match *node {
hir::ExprBox(..) |
hir::ExprArray(..) |
hir::ExprCall(..) |
@ -578,41 +562,33 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::E
hir::ExprBreak(..) |
hir::ExprAgain(..) |
hir::ExprRet(..) |
hir::ExprYield(..) |
hir::ExprYield(..) |
hir::ExprInlineAsm(..) |
hir::ExprRepeat(..) |
hir::ExprTup(..) => {
// For these we only hash the span when debuginfo is on.
(false, NodeIdHashingMode::CheckedIgnore)
}
// For the following, spans might be significant because of
// panic messages indicating the source location.
hir::ExprBinary(op, ..) => {
(hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::CheckedIgnore)
}
hir::ExprUnary(op, _) => {
(hcx.unop_can_panic_at_runtime(op), NodeIdHashingMode::CheckedIgnore)
}
hir::ExprAssignOp(op, ..) => {
(hcx.binop_can_panic_at_runtime(op.node), NodeIdHashingMode::CheckedIgnore)
}
hir::ExprIndex(..) => {
(true, NodeIdHashingMode::CheckedIgnore)
}
// For these we don't care about the span, but want to hash the
// trait in scope
hir::ExprTup(..) |
hir::ExprMethodCall(..) |
hir::ExprPath(..) |
hir::ExprStruct(..) |
hir::ExprField(..) => {
(false, NodeIdHashingMode::HashTraitsInScope)
// For these we only hash the span when debuginfo is on.
false
}
// For the following, spans might be significant because of
// panic messages indicating the source location.
hir::ExprBinary(op, ..) => {
hcx.binop_can_panic_at_runtime(op.node)
}
hir::ExprUnary(op, _) => {
hcx.unop_can_panic_at_runtime(op)
}
hir::ExprAssignOp(op, ..) => {
hcx.binop_can_panic_at_runtime(op.node)
}
hir::ExprIndex(..) => {
true
}
};
hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
id.hash_stable(hcx, hasher);
});
if spans_always_on {
hcx.while_hashing_spans(true, |hcx| {
span.hash_stable(hcx, hasher);
@ -815,7 +791,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::V
// No fields to hash.
}
hir::Visibility::Restricted { ref path, id } => {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashTraitsInScope, |hcx| {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
id.hash_stable(hcx, hasher);
});
path.hash_stable(hcx, hasher);
@ -904,16 +880,13 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) {
let (node_id_hashing_mode, hash_spans) = match self.node {
let hash_spans = match self.node {
hir::ItemStatic(..) |
hir::ItemConst(..) |
hir::ItemFn(..) => {
(NodeIdHashingMode::CheckedIgnore, hcx.hash_spans())
hcx.hash_spans()
}
hir::ItemUse(..) => {
(NodeIdHashingMode::HashTraitsInScope, false)
}
hir::ItemUse(..) |
hir::ItemExternCrate(..) |
hir::ItemForeignMod(..) |
hir::ItemGlobalAsm(..) |
@ -925,14 +898,14 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemUnion(..) => {
(NodeIdHashingMode::CheckedIgnore, false)
false
}
};
let hir::Item {
name,
ref attrs,
id,
id: _,
hir_id: _,
ref node,
ref vis,
@ -941,9 +914,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
hcx.hash_hir_item_like(attrs, |hcx| {
hcx.while_hashing_spans(hash_spans, |hcx| {
hcx.with_node_id_hashing_mode(node_id_hashing_mode, |hcx| {
id.hash_stable(hcx, hasher);
});
name.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
node.hash_stable(hcx, hasher);
@ -1049,6 +1019,18 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::B
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
type KeyType = (DefPathHash, hir::ItemLocalId);
#[inline]
fn to_stable_hash_key(&self,
hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
-> (DefPathHash, hir::ItemLocalId) {
let hir::BodyId { node_id } = *self;
node_id.to_stable_hash_key(hcx)
}
}
impl_stable_hash_for!(struct hir::InlineAsmOutput {
constraint,
is_rw,
@ -1151,7 +1133,17 @@ for hir::def_id::DefIndex {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
hasher: &mut StableHasher<W>) {
DefId::local(*self).hash_stable(hcx, hasher);
hcx.tcx().hir.definitions().def_path_hash(*self).hash_stable(hcx, hasher);
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>>
for hir::def_id::DefIndex {
type KeyType = DefPathHash;
#[inline]
fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a, 'gcx, 'tcx>) -> DefPathHash {
hcx.tcx().hir.definitions().def_path_hash(*self)
}
}
@ -1170,6 +1162,11 @@ for ::middle::lang_items::LangItem {
}
}
impl_stable_hash_for!(struct ::middle::lang_items::LanguageItems {
items,
missing
});
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
for hir::TraitCandidate {
fn hash_stable<W: StableHasherResult>(&self,
@ -1186,3 +1183,8 @@ for hir::TraitCandidate {
});
}
}
impl_stable_hash_for!(struct hir::Freevar {
def,
span
});

View File

@ -0,0 +1,26 @@
// 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
//! that don't fit into any of the other impls_xxx modules.
impl_stable_hash_for!(enum ::session::search_paths::PathKind {
Native,
Crate,
Dependency,
Framework,
ExternFlag,
All
});
impl_stable_hash_for!(enum ::rustc_back::PanicStrategy {
Abort,
Unwind
});

View File

@ -18,17 +18,17 @@ use std::mem;
use syntax::ast;
use syntax::parse::token;
use syntax::symbol::InternedString;
use syntax::tokenstream;
use syntax_pos::{Span, FileMap};
use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
StableHasher, StableHasherResult};
use rustc_data_structures::accumulate_vec::AccumulateVec;
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
for ::syntax::symbol::InternedString {
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for InternedString {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
@ -38,6 +38,17 @@ for ::syntax::symbol::InternedString {
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for InternedString {
type KeyType = InternedString;
#[inline]
fn to_stable_hash_key(&self,
_: &StableHashingContext<'a, 'gcx, 'tcx>)
-> InternedString {
self.clone()
}
}
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Name {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
@ -47,6 +58,17 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::N
}
}
impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for ast::Name {
type KeyType = InternedString;
#[inline]
fn to_stable_hash_key(&self,
_: &StableHashingContext<'a, 'gcx, 'tcx>)
-> InternedString {
self.as_str()
}
}
impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
Att,
Intel

View File

@ -24,6 +24,7 @@ mod impls_const_math;
mod impls_cstore;
mod impls_hir;
mod impls_mir;
mod impls_misc;
mod impls_ty;
mod impls_syntax;

View File

@ -132,7 +132,7 @@ pub struct NativeLibrary {
pub kind: NativeLibraryKind,
pub name: Symbol,
pub cfg: Option<ast::MetaItem>,
pub foreign_items: Vec<DefIndex>,
pub foreign_items: Vec<DefId>,
}
pub enum LoadedMacro {

View File

@ -192,8 +192,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
let mut collector = LanguageItemCollector::new(tcx);
for &cnum in tcx.crates().iter() {
for &(index, item_index) in tcx.defined_lang_items(cnum).iter() {
let def_id = DefId { krate: cnum, index: index };
for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
collector.collect_item(item_index, def_id);
}
}

View File

@ -65,6 +65,11 @@ pub struct DeprecationEntry {
origin: Option<HirId>,
}
impl_stable_hash_for!(struct self::DeprecationEntry {
attr,
origin
});
impl DeprecationEntry {
fn local(attr: Deprecation, id: HirId) -> DeprecationEntry {
DeprecationEntry {
@ -102,6 +107,13 @@ pub struct Index<'tcx> {
active_features: FxHashSet<Symbol>,
}
impl_stable_hash_for!(struct self::Index<'tcx> {
stab_map,
depr_map,
staged_api,
active_features
});
// A private tree-walker for producing an Index.
struct Annotator<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,

View File

@ -1083,6 +1083,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
None
};
// FIXME(mw): Each of the Vecs in the trait_map should be brought into
// a deterministic order here. Otherwise we might end up with
// unnecessarily unstable incr. comp. hashes.
let mut trait_map = FxHashMap();
for (k, v) in resolutions.trait_map {
let hir_id = hir.node_to_hir_id(k);
@ -1171,17 +1174,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
pub fn lang_items(self) -> Rc<middle::lang_items::LanguageItems> {
// FIXME(#42293) Right now we insert a `with_ignore` node in the dep
// graph here to ignore the fact that `get_lang_items` below depends on
// the entire crate. For now this'll prevent false positives of
// recompiling too much when anything changes.
//
// Once red/green incremental compilation lands we should be able to
// remove this because while the crate changes often the lint level map
// will change rarely.
self.dep_graph.with_ignore(|| {
self.get_lang_items(LOCAL_CRATE)
})
self.get_lang_items(LOCAL_CRATE)
}
pub fn stability(self) -> Rc<stability::Index<'tcx>> {
@ -2198,7 +2191,15 @@ pub fn provide(providers: &mut ty::maps::Providers) {
};
providers.get_lang_items = |tcx, id| {
assert_eq!(id, LOCAL_CRATE);
Rc::new(middle::lang_items::collect(tcx))
// FIXME(#42293) Right now we insert a `with_ignore` node in the dep
// graph here to ignore the fact that `get_lang_items` below depends on
// the entire crate. For now this'll prevent false positives of
// recompiling too much when anything changes.
//
// Once red/green incremental compilation lands we should be able to
// remove this because while the crate changes often the lint level map
// will change rarely.
tcx.dep_graph.with_ignore(|| Rc::new(middle::lang_items::collect(tcx)))
};
providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned();
providers.maybe_unused_trait_import = |tcx, id| {

View File

@ -1400,7 +1400,7 @@ define_maps! { <'tcx>
[] fn extern_mod_stmt_cnum: ExternModStmtCnum(DefId) -> Option<CrateNum>,
[] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc<LanguageItems>,
[] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefIndex, usize)>>,
[] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefId, usize)>>,
[] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc<Vec<LangItem>>,
[] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body,
[] fn visible_parent_map: visible_parent_map_node(CrateNum)

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::hash::{Hash, Hasher};
use std::hash::{Hash, Hasher, BuildHasher};
use std::marker::PhantomData;
use std::mem;
use blake2b::Blake2bHasher;
@ -222,6 +222,14 @@ pub trait HashStable<CTX> {
hasher: &mut StableHasher<W>);
}
/// Implement this for types that can be turned into stable keys like, for
/// example, for DefId that can be converted to a DefPathHash. This is used for
/// bringing maps into a predictable order before hashing them.
pub trait ToStableHashKey<HCX> {
type KeyType: Ord + Clone + Sized + HashStable<HCX>;
fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
}
// 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 {
@ -423,34 +431,6 @@ impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
}
}
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>,
{
@ -473,3 +453,66 @@ impl<I: ::indexed_vec::Idx, CTX> HashStable<CTX> for ::indexed_set::IdxSetBuf<I>
self.words().hash_stable(ctx, hasher);
}
}
impl_stable_hash_via_hash!(::std::path::Path);
impl_stable_hash_via_hash!(::std::path::PathBuf);
impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
where K: ToStableHashKey<HCX> + Eq + Hash,
V: HashStable<HCX>,
R: BuildHasher,
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut HCX,
hasher: &mut StableHasher<W>) {
let mut entries: Vec<_> = self.iter()
.map(|(k, v)| (k.to_stable_hash_key(hcx), v))
.collect();
entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
entries.hash_stable(hcx, hasher);
}
}
impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R>
where K: ToStableHashKey<HCX> + Eq + Hash,
R: BuildHasher,
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut HCX,
hasher: &mut StableHasher<W>) {
let mut keys: Vec<_> = self.iter()
.map(|k| k.to_stable_hash_key(hcx))
.collect();
keys.sort_unstable();
keys.hash_stable(hcx, hasher);
}
}
impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
where K: ToStableHashKey<HCX>,
V: HashStable<HCX>,
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut HCX,
hasher: &mut StableHasher<W>) {
let mut entries: Vec<_> = self.iter()
.map(|(k, v)| (k.to_stable_hash_key(hcx), v))
.collect();
entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
entries.hash_stable(hcx, hasher);
}
}
impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
where K: ToStableHashKey<HCX>,
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut HCX,
hasher: &mut StableHasher<W>) {
let mut keys: Vec<_> = self.iter()
.map(|k| k.to_stable_hash_key(hcx))
.collect();
keys.sort_unstable();
keys.hash_stable(hcx, hasher);
}
}

View File

@ -31,7 +31,7 @@ use std::cell::RefCell;
use std::hash::Hash;
use rustc::dep_graph::{DepNode, DepKind};
use rustc::hir;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use rustc::hir::map::DefPathHash;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ich::{Fingerprint, StableHashingContext};
@ -96,7 +96,7 @@ struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
fn compute_and_store_ich_for_item_like<T>(&mut self,
dep_node: DepNode,
def_index: DefIndex,
hash_bodies: bool,
item_like: T)
where T: HashStable<StableHashingContext<'a, 'tcx, 'tcx>>
@ -108,6 +108,8 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
return
}
let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(def_index);
let mut hasher = IchHasher::new();
self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| {
item_like.hash_stable(hcx, &mut hasher);
@ -115,6 +117,11 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
let bytes_hashed = hasher.bytes_hashed();
let item_hash = hasher.finish();
let dep_node = if hash_bodies {
def_path_hash.to_dep_node(DepKind::HirBody)
} else {
def_path_hash.to_dep_node(DepKind::Hir)
};
debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
self.hashes.insert(dep_node, item_hash);
@ -123,6 +130,14 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
bytes_hashed;
tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
if hash_bodies {
let in_scope_traits_map = tcx.in_scope_traits_map(def_index);
let mut hasher = IchHasher::new();
in_scope_traits_map.hash_stable(&mut self.hcx, &mut hasher);
let dep_node = def_path_hash.to_dep_node(DepKind::InScopeTraits);
self.hashes.insert(dep_node, hasher.finish());
}
}
fn compute_crate_hash(&mut self) {
@ -145,6 +160,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
// This `match` determines what kinds of nodes
// go into the SVH:
match item_dep_node.kind {
DepKind::InScopeTraits |
DepKind::Hir |
DepKind::HirBody => {
// We want to incoporate these into the
@ -195,11 +211,10 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
body_ids: _,
} = *krate;
let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(CRATE_DEF_INDEX);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX,
false,
(module, (span, attrs)));
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX,
true,
(module, (span, attrs)));
}
@ -251,34 +266,31 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
let def_id = self.hcx.tcx().hir.local_def_id(item.id);
let def_path_hash = self.hcx.tcx().def_path_hash(def_id);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
self.compute_and_store_ich_for_item_like(def_index,
false,
item);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
self.compute_and_store_ich_for_item_like(def_index,
true,
item);
}
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
let def_id = self.hcx.tcx().hir.local_def_id(item.id);
let def_path_hash = self.hcx.tcx().def_path_hash(def_id);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
self.compute_and_store_ich_for_item_like(def_index,
false,
item);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
self.compute_and_store_ich_for_item_like(def_index,
true,
item);
}
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
let def_id = self.hcx.tcx().hir.local_def_id(item.id);
let def_path_hash = self.hcx.tcx().def_path_hash(def_id);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
let def_index = self.hcx.tcx().hir.local_def_id(item.id).index;
self.compute_and_store_ich_for_item_like(def_index,
false,
item);
self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
self.compute_and_store_ich_for_item_like(def_index,
true,
item);
}
@ -301,12 +313,11 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
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);
let def_path_hash = tcx.def_path_hash(def_id);
visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir),
let def_index = tcx.hir.local_def_id(macro_def.id).index;
visitor.compute_and_store_ich_for_item_like(def_index,
false,
macro_def);
visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody),
visitor.compute_and_store_ich_for_item_like(def_index,
true,
macro_def);
}

View File

@ -49,6 +49,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
match dep_node.kind {
DepKind::Krate |
DepKind::Hir |
DepKind::InScopeTraits |
DepKind::HirBody =>
true,
DepKind::MetaData => {
@ -66,6 +67,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
}
// HIR nodes (which always come from our crate) are an input:
DepKind::InScopeTraits |
DepKind::Hir |
DepKind::HirBody => {
Some(self.incremental_hashes_map[dep_node])

View File

@ -104,6 +104,7 @@ fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool {
match dep_node.kind {
DepKind::Hir |
DepKind::HirBody |
DepKind::InScopeTraits |
DepKind::MetaData => {
dep_node.extract_def_id(tcx).is_some()
}

View File

@ -301,7 +301,10 @@ impl<'a> CrateLoader<'a> {
.decode(&cmeta)
.filter(|lib| relevant_lib(self.sess, lib) &&
lib.kind == cstore::NativeLibraryKind::NativeUnknown)
.flat_map(|lib| lib.foreign_items.into_iter())
.flat_map(|lib| {
assert!(lib.foreign_items.iter().all(|def_id| def_id.krate == cnum));
lib.foreign_items.into_iter().map(|def_id| def_id.index)
})
.collect();
cmeta.dllimport_foreign_items = dllimports;

View File

@ -264,7 +264,7 @@ pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
tcx.native_libraries(id.krate)
.iter()
.filter(|lib| native_libs::relevant_lib(&tcx.sess, lib))
.find(|l| l.foreign_items.contains(&id.index))
.find(|l| l.foreign_items.contains(&id))
.map(|l| l.kind)
},
native_libraries: |tcx, cnum| {

View File

@ -659,10 +659,11 @@ impl<'a, 'tcx> CrateMetadata {
}
/// Iterates over the language items in the given crate.
pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> {
pub fn get_lang_items(&self) -> Vec<(DefId, usize)> {
self.root
.lang_items
.decode(self)
.map(|(def_index, index)| (self.local_def_id(def_index), index))
.collect()
}

View File

@ -96,7 +96,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
list[0].meta_item().unwrap().clone()
});
let foreign_items = fm.items.iter()
.map(|it| self.tcx.hir.local_def_id(it.id).index)
.map(|it| self.tcx.hir.local_def_id(it.id))
.collect();
let lib = NativeLibrary {
name: n,

View File

@ -15,8 +15,7 @@
//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts};
use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, Lookup};
use rustc::mir::transform::{MirPass, MirSource};
@ -80,45 +79,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
self.super_statement(block, statement, location);
self.in_validation_statement = false;
}
fn visit_const_val(&mut self,
const_val: &mut ConstVal<'tcx>,
_: Location) {
erase_const_val(self.tcx, const_val);
self.super_const_val(const_val);
fn erase_const_val<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
const_val: &mut ConstVal<'tcx>) {
match *const_val {
ConstVal::Float(_) |
ConstVal::Integral(_) |
ConstVal::Str(_) |
ConstVal::ByteStr(_) |
ConstVal::Bool(_) |
ConstVal::Char(_) |
ConstVal::Variant(_) => {
// nothing to do
}
ConstVal::Function(_, ref mut substs) => {
*substs = tcx.erase_regions(&{*substs});
}
ConstVal::Struct(ref mut field_map) => {
for (_, field_val) in field_map {
erase_const_val(tcx, field_val);
}
}
ConstVal::Tuple(ref mut fields) |
ConstVal::Array(ref mut fields) => {
for field_val in fields {
erase_const_val(tcx, field_val);
}
}
ConstVal::Repeat(ref mut expr, _) => {
erase_const_val(tcx, &mut **expr);
}
}
}
}
}
pub struct EraseRegions;

View File

@ -12,6 +12,7 @@
// scope.
// revisions: rpass1 rpass2
// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
@ -47,13 +48,15 @@ mod mod3 {
use Trait2;
#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_dirty(label="HirBody", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
#[rustc_dirty(label="TypeckTables", cfg="rpass2")]
fn bar() {
().method();
}
#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
#[rustc_clean(label="TypeckTables", cfg="rpass2")]
fn baz() {
22; // no method call, traits in scope don't matter
}