about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-08-20 11:52:01 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-08-20 11:52:01 -0400
commit0595a3a8fa762af28caf4cec9eecd59ea3003163 (patch)
tree1ffad9698c595e0f147034724429d87df335cbe0 /src
parent6bd80d11163771293ea7bf75a4513af76b754a41 (diff)
downloadrust-0595a3a8fa762af28caf4cec9eecd59ea3003163.tar.gz
rust-0595a3a8fa762af28caf4cec9eecd59ea3003163.zip
hash the traits-in-scope determinstically
Experimentally, this fixes the poor re-use observed in
libsyntex-syntax. I'm not sure how to make a regression test for this,
though, given the non-deterministic nature of it.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_incremental/calculate_svh/svh_visitor.rs33
1 files changed, 24 insertions, 9 deletions
diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs
index c06b223ce21..1e00e0fc562 100644
--- a/src/librustc_incremental/calculate_svh/svh_visitor.rs
+++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs
@@ -25,25 +25,33 @@ use rustc::hir::def::{Def, PathResolution};
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit as visit;
 use rustc::hir::intravisit::{Visitor, FnKind};
-use rustc::hir::map::DefPath;
 use rustc::ty::TyCtxt;
+use rustc::util::nodemap::DefIdMap;
 
 use std::hash::{Hash, SipHasher};
 
 pub struct StrictVersionHashVisitor<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub st: &'a mut SipHasher,
+
+    // collect a deterministic hash of def-ids that we have seen
+    def_id_hashes: DefIdMap<u64>,
 }
 
 impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
     pub fn new(st: &'a mut SipHasher,
                tcx: TyCtxt<'a, 'tcx, 'tcx>)
                -> Self {
-        StrictVersionHashVisitor { st: st, tcx: tcx }
+        StrictVersionHashVisitor { st: st, tcx: tcx, def_id_hashes: DefIdMap() }
     }
 
-    fn hash_def_path(&mut self, path: &DefPath) {
-        path.deterministic_hash_to(self.tcx, self.st);
+    fn compute_def_id_hash(&mut self, def_id: DefId) -> u64 {
+        let tcx = self.tcx;
+        *self.def_id_hashes.entry(def_id)
+                           .or_insert_with(|| {
+                               let def_path = tcx.def_path(def_id);
+                               def_path.deterministic_hash(tcx)
+                           })
     }
 }
 
@@ -376,15 +384,22 @@ impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
         if let Some(traits) = self.tcx.trait_map.get(&id) {
             debug!("hash_resolve: id={:?} traits={:?} st={:?}", id, traits, self.st);
             traits.len().hash(self.st);
-            for candidate in traits {
-                self.hash_def_id(candidate.def_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: Vec<_> =
+                traits.iter()
+                      .map(|&TraitCandidate { def_id, import_id: _ }| {
+                          self.compute_def_id_hash(def_id)
+                      })
+                      .collect();
+            candidates.sort();
+            candidates.hash(self.st);
         }
     }
 
     fn hash_def_id(&mut self, def_id: DefId) {
-        let def_path = self.tcx.def_path(def_id);
-        self.hash_def_path(&def_path);
+        self.compute_def_id_hash(def_id).hash(self.st);
     }
 
     fn hash_partial_def(&mut self, def: &PathResolution) {