about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-09-14 17:40:37 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-09-20 11:21:25 +0200
commit3b75a3dfeaf8261bd59343792b3650550be86c95 (patch)
tree61d2b82a1873d96daf3c85c7fe312c114adbcc8e
parent54996837a399421f8d691c6901eea5ab20a30f46 (diff)
downloadrust-3b75a3dfeaf8261bd59343792b3650550be86c95.tar.gz
rust-3b75a3dfeaf8261bd59343792b3650550be86c95.zip
incr.comp.: Make sure traits_in_scope results are hashed in a stable way.
-rw-r--r--src/librustc/ich/hcx.rs5
-rw-r--r--src/librustc/ich/impls_hir.rs19
-rw-r--r--src/librustc/ty/context.rs17
-rw-r--r--src/librustc/ty/maps/mod.rs3
-rw-r--r--src/librustc_data_structures/stable_hasher.rs32
5 files changed, 67 insertions, 9 deletions
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 64fc63002da..36d2454eacc 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -169,6 +169,11 @@ impl<'gcx> StableHashingContext<'gcx> {
     }
 
     #[inline]
+    pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
+        self.definitions.node_to_hir_id(node_id)
+    }
+
+    #[inline]
     pub fn hash_spans(&self) -> bool {
         self.hash_spans
     }
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 9582b03ce1c..ee4e2536e46 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1160,6 +1160,25 @@ for hir::TraitCandidate {
     }
 }
 
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::TraitCandidate {
+    type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);
+
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'gcx>)
+                          -> Self::KeyType {
+        let hir::TraitCandidate {
+            def_id,
+            import_id,
+        } = *self;
+
+        let import_id = import_id.map(|node_id| hcx.node_to_hir_id(node_id))
+                                 .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner),
+                                                hir_id.local_id));
+        (hcx.def_path_hash(def_id), import_id)
+    }
+}
+
+
 impl_stable_hash_for!(struct hir::Freevar {
     def,
     span
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 874bb426dc5..cccdaed6eca 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -50,8 +50,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
-                                           StableHasher, StableHasherResult};
-
+                                           StableHasher, StableHasherResult,
+                                           StableVec};
 use arena::{TypedArena, DroplessArena};
 use rustc_const_math::{ConstInt, ConstUsize};
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -828,7 +828,9 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
-    trait_map: FxHashMap<DefIndex, Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>,
+    trait_map: FxHashMap<DefIndex,
+                         Rc<FxHashMap<ItemLocalId,
+                                      Rc<StableVec<TraitCandidate>>>>>,
 
     /// Export map produced by name resolution.
     export_map: FxHashMap<DefId, Rc<Vec<Export>>>,
@@ -1081,15 +1083,14 @@ 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);
             let map = trait_map.entry(hir_id.owner)
                 .or_insert_with(|| Rc::new(FxHashMap()));
-            Rc::get_mut(map).unwrap().insert(hir_id.local_id, Rc::new(v));
+            Rc::get_mut(map).unwrap()
+                            .insert(hir_id.local_id,
+                                    Rc::new(StableVec::new(v)));
         }
         let mut defs = FxHashMap();
         for (k, v) in named_region_map.defs {
@@ -2103,7 +2104,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         lint::struct_lint_level(self.sess, lint, level, src, None, msg)
     }
 
-    pub fn in_scope_traits(self, id: HirId) -> Option<Rc<Vec<TraitCandidate>>> {
+    pub fn in_scope_traits(self, id: HirId) -> Option<Rc<StableVec<TraitCandidate>>> {
         self.in_scope_traits_map(id.owner)
             .and_then(|map| map.get(&id.local_id).cloned())
     }
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index c08ad68eddd..7a8cecbf812 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -42,6 +42,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stable_hasher::StableVec;
 use std::cell::{RefCell, Cell};
 
 use std::ops::Deref;
@@ -259,7 +260,7 @@ define_maps! { <'tcx>
 
     [] fn specializes: specializes_node((DefId, DefId)) -> bool,
     [] fn in_scope_traits_map: InScopeTraits(DefIndex)
-        -> Option<Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>,
+        -> Option<Rc<FxHashMap<ItemLocalId, Rc<StableVec<TraitCandidate>>>>>,
     [] fn module_exports: ModuleExports(DefId) -> Option<Rc<Vec<Export>>>,
     [] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,
 
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index f6b23af2f73..a5df250b338 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -558,3 +558,35 @@ pub fn hash_stable_hashmap<HCX, K, V, R, SK, F, W>(
     entries.hash_stable(hcx, hasher);
 }
 
+pub struct StableVec<T>(Vec<T>);
+
+impl<T> StableVec<T> {
+
+    pub fn new(v: Vec<T>) -> Self {
+        StableVec(v)
+    }
+}
+
+impl<T> ::std::ops::Deref for StableVec<T> {
+    type Target = Vec<T>;
+
+    fn deref(&self) -> &Vec<T> {
+        &self.0
+    }
+}
+
+impl<T, HCX> HashStable<HCX> for StableVec<T>
+    where T: HashStable<HCX> + ToStableHashKey<HCX>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let StableVec(ref v) = *self;
+
+        let mut sorted: Vec<_> = v.iter()
+                                  .map(|x| x.to_stable_hash_key(hcx))
+                                  .collect();
+        sorted.sort_unstable();
+        sorted.hash_stable(hcx, hasher);
+    }
+}