diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 06469c16bc2..1dcc9272d4e 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -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; diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index f4fa376347a..daf1ff8ad2b 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -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> for ast::N fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - 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> 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> for Span { // Hash a span in a stable way. We can't directly hash the span's BytePos diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs index dad5c35c1e8..057a83ebbe3 100644 --- a/src/librustc/ich/impls_cstore.rs +++ b/src/librustc/ich/impls_cstore.rs @@ -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 +}); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index a4cbcf04111..9da147472ce 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -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> for DefId { #[inline] @@ -29,14 +29,12 @@ impl<'a, 'gcx, 'tcx> HashStable> for DefId } } -impl<'a, 'gcx, 'tcx> HashStable> for DefIdSet -{ - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, - hasher: &mut StableHasher) { - ich::hash_stable_hashset(hcx, hasher, self, |hcx, def_id| { - hcx.def_path_hash(*def_id) - }); +impl<'a, 'gcx, 'tcx> ToStableHashKey> 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> 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> 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> for CrateNum { #[inline] @@ -68,8 +77,30 @@ impl<'a, 'gcx, 'tcx> HashStable> for CrateN } } +impl<'a, 'gcx, 'tcx> ToStableHashKey> 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> +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> for hir::T fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - 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> for hir::T hasher: &mut StableHasher) { 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> 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> 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> for hir::P fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - 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> for hir::E hasher: &mut StableHasher) { 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> 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> 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> for hir::I fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - 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> 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> 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> for hir::B } } +impl<'a, 'gcx, 'tcx> ToStableHashKey> 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(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { - DefId::local(*self).hash_stable(hcx, hasher); + hcx.tcx().hir.definitions().def_path_hash(*self).hash_stable(hcx, hasher); + } +} + +impl<'a, 'gcx, 'tcx> ToStableHashKey> +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> for hir::TraitCandidate { fn hash_stable(&self, @@ -1186,3 +1183,8 @@ for hir::TraitCandidate { }); } } + +impl_stable_hash_for!(struct hir::Freevar { + def, + span +}); diff --git a/src/librustc/ich/impls_misc.rs b/src/librustc/ich/impls_misc.rs new file mode 100644 index 00000000000..951315fb4a8 --- /dev/null +++ b/src/librustc/ich/impls_misc.rs @@ -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 or the MIT license +// , 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 +}); diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index e52be70190c..a75527c14bd 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -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> -for ::syntax::symbol::InternedString { +impl<'a, 'gcx, 'tcx> HashStable> for InternedString { #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, @@ -38,6 +38,17 @@ for ::syntax::symbol::InternedString { } } +impl<'a, 'gcx, 'tcx> ToStableHashKey> for InternedString { + type KeyType = InternedString; + + #[inline] + fn to_stable_hash_key(&self, + _: &StableHashingContext<'a, 'gcx, 'tcx>) + -> InternedString { + self.clone() + } +} + impl<'a, 'gcx, 'tcx> HashStable> for ast::Name { #[inline] fn hash_stable(&self, @@ -47,6 +58,17 @@ impl<'a, 'gcx, 'tcx> HashStable> for ast::N } } +impl<'a, 'gcx, 'tcx> ToStableHashKey> 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 diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index c24064eb27c..5558534b71d 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -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; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index bea6ef4dc11..7c60c6d6430 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -132,7 +132,7 @@ pub struct NativeLibrary { pub kind: NativeLibraryKind, pub name: Symbol, pub cfg: Option, - pub foreign_items: Vec, + pub foreign_items: Vec, } pub enum LoadedMacro { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 7a6f4fdbb03..0c0b9697338 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -192,8 +192,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option { 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); } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 977102ec1ad..89049958309 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -65,6 +65,11 @@ pub struct DeprecationEntry { origin: Option, } +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, } +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>, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 945a0814427..7edc55e8a9f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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 { - // 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> { @@ -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| { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index c96ae862265..fc803d1c849 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -1400,7 +1400,7 @@ define_maps! { <'tcx> [] fn extern_mod_stmt_cnum: ExternModStmtCnum(DefId) -> Option, [] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc, - [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc>, + [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc>, [] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc>, [] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body, [] fn visible_parent_map: visible_parent_map_node(CrateNum) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index f80cbfadf2e..1b2d09bef93 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -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 { hasher: &mut StableHasher); } +/// 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 { + type KeyType: Ord + Clone + Sized + HashStable; + 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 HashStable for ::std::mem::Discriminant { } } -impl HashStable for ::std::collections::BTreeMap - where K: Ord + HashStable, - V: HashStable, -{ - fn hash_stable(&self, - ctx: &mut CTX, - hasher: &mut StableHasher) { - self.len().hash_stable(ctx, hasher); - for (k, v) in self { - k.hash_stable(ctx, hasher); - v.hash_stable(ctx, hasher); - } - } -} - -impl HashStable for ::std::collections::BTreeSet - where T: Ord + HashStable, -{ - fn hash_stable(&self, - ctx: &mut CTX, - hasher: &mut StableHasher) { - self.len().hash_stable(ctx, hasher); - for v in self { - v.hash_stable(ctx, hasher); - } - } -} - impl HashStable for ::indexed_vec::IndexVec where T: HashStable, { @@ -473,3 +453,66 @@ impl HashStable for ::indexed_set::IdxSetBuf self.words().hash_stable(ctx, hasher); } } + +impl_stable_hash_via_hash!(::std::path::Path); +impl_stable_hash_via_hash!(::std::path::PathBuf); + +impl HashStable for ::std::collections::HashMap + where K: ToStableHashKey + Eq + Hash, + V: HashStable, + R: BuildHasher, +{ + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { + 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 HashStable for ::std::collections::HashSet + where K: ToStableHashKey + Eq + Hash, + R: BuildHasher, +{ + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { + let mut keys: Vec<_> = self.iter() + .map(|k| k.to_stable_hash_key(hcx)) + .collect(); + keys.sort_unstable(); + keys.hash_stable(hcx, hasher); + } +} + +impl HashStable for ::std::collections::BTreeMap + where K: ToStableHashKey, + V: HashStable, +{ + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { + 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 HashStable for ::std::collections::BTreeSet + where K: ToStableHashKey, +{ + fn hash_stable(&self, + hcx: &mut HCX, + hasher: &mut StableHasher) { + let mut keys: Vec<_> = self.iter() + .map(|k| k.to_stable_hash_key(hcx)) + .collect(); + keys.sort_unstable(); + keys.hash_stable(hcx, hasher); + } +} diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index 94400890c56..d8e201d3acd 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -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(&mut self, - dep_node: DepNode, + def_index: DefIndex, hash_bodies: bool, item_like: T) where T: HashStable> @@ -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); } diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 44d6788c773..8355f319139 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -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]) diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index ba638289fdf..9865ea8c285 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -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() } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index dc6c260ec71..39bdf88925e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -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; diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 3a116160bca..e4de27ee15e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -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| { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1c4f1c63486..4696759817f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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() } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 669681d2aad..cc332acb5b0 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -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, diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 6ed928ca09d..dc18cdd8f0d 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -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; diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs index 0a36e3c693e..7f4e2b0f176 100644 --- a/src/test/incremental/ich_method_call_trait_scope.rs +++ b/src/test/incremental/ich_method_call_trait_scope.rs @@ -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 }