about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-05-06 05:01:09 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-05-18 10:11:35 -0400
commit0082fc0ad4d9f8c1cbac7326be2db01f866bfef1 (patch)
tree4cfe57ee498fb068533b6d6885af1a20f2ad2f72
parent08837d2975d5c642a4e625501ef452f43e217dc6 (diff)
downloadrust-0082fc0ad4d9f8c1cbac7326be2db01f866bfef1.tar.gz
rust-0082fc0ad4d9f8c1cbac7326be2db01f866bfef1.zip
change svh to store a u64
We used to store a u64 converted to a String for some reason. Now we
don't.
-rw-r--r--src/librustc/hir/svh.rs66
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc_incremental/calculate_svh.rs13
-rw-r--r--src/librustc_metadata/decoder.rs6
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_metadata/loader.rs2
6 files changed, 38 insertions, 55 deletions
diff --git a/src/librustc/hir/svh.rs b/src/librustc/hir/svh.rs
index 1536f884b09..f0294ad633a 100644
--- a/src/librustc/hir/svh.rs
+++ b/src/librustc/hir/svh.rs
@@ -10,60 +10,34 @@
 
 //! Calculation and management of a Strict Version Hash for crates
 //!
-//! # Today's ABI problem
-//!
-//! In today's implementation of rustc, it is incredibly difficult to achieve
-//! forward binary compatibility without resorting to C-like interfaces. Within
-//! rust code itself, abi details such as symbol names suffer from a variety of
-//! unrelated factors to code changing such as the "def id drift" problem. This
-//! ends up yielding confusing error messages about metadata mismatches and
-//! such.
-//!
-//! The core of this problem is when an upstream dependency changes and
-//! downstream dependents are not recompiled. This causes compile errors because
-//! the upstream crate's metadata has changed but the downstream crates are
-//! still referencing the older crate's metadata.
-//!
-//! This problem exists for many reasons, the primary of which is that rust does
-//! not currently support forwards ABI compatibility (in place upgrades of a
-//! crate).
-//!
-//! # SVH and how it alleviates the problem
-//!
-//! With all of this knowledge on hand, this module contains the implementation
-//! of a notion of a "Strict Version Hash" for a crate. This is essentially a
-//! hash of all contents of a crate which can somehow be exposed to downstream
-//! crates.
-//!
-//! This hash is currently calculated by just hashing the AST, but this is
-//! obviously wrong (doc changes should not result in an incompatible ABI).
-//! Implementation-wise, this is required at this moment in time.
-//!
-//! By encoding this strict version hash into all crate's metadata, stale crates
-//! can be detected immediately and error'd about by rustc itself.
-//!
-//! # Relevant links
-//!
-//! Original issue: https://github.com/rust-lang/rust/issues/10207
+//! The SVH is used for incremental compilation to track when HIR
+//! nodes have changed between compilations, and also to detect
+//! mismatches where we have two versions of the same crate that were
+//! compiled from distinct sources.
 
 use std::fmt;
+use std::hash::{Hash, Hasher};
 
-#[derive(Clone, Eq, Hash, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub struct Svh {
-    hash: String,
+    hash: u64,
 }
 
 impl Svh {
     /// Create a new `Svh` given the hash. If you actually want to
     /// compute the SVH from some HIR, you want the `calculate_svh`
-    /// function found in `librustc_trans`.
-    pub fn new(hash: String) -> Svh {
-        assert!(hash.len() == 16);
+    /// function found in `librustc_incremental`.
+    pub fn new(hash: u64) -> Svh {
         Svh { hash: hash }
     }
 
-    pub fn from_hash(hash: u64) -> Svh {
-        return Svh::new((0..64).step_by(4).map(|i| hex(hash >> i)).collect());
+    pub fn as_u64(&self) -> u64 {
+        self.hash
+    }
+
+    pub fn to_string(&self) -> String {
+        let hash = self.hash;
+        return (0..64).step_by(4).map(|i| hex(hash >> i)).collect();
 
         fn hex(b: u64) -> char {
             let b = (b & 0xf) as u8;
@@ -74,14 +48,16 @@ impl Svh {
             b as char
         }
     }
+}
 
-    pub fn as_str<'a>(&'a self) -> &'a str {
-        &self.hash
+impl Hash for Svh {
+    fn hash<H>(&self, state: &mut H) where H: Hasher {
+        self.hash.to_le().hash(state);
     }
 }
 
 impl fmt::Display for Svh {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad(self.as_str())
+        f.pad(&self.to_string())
     }
 }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 08909861d3f..4f6188ea3c5 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -368,7 +368,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 } else {
                     tcx.sess.cstore.crate_hash(did.krate)
                 };
-                h.as_str().hash(state);
+                h.hash(state);
                 did.index.hash(state);
             };
             let mt = |state: &mut SipHasher, mt: TypeAndMut| {
diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs
index f134f3c3f10..24ecce11487 100644
--- a/src/librustc_incremental/calculate_svh.rs
+++ b/src/librustc_incremental/calculate_svh.rs
@@ -72,12 +72,14 @@ impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx, 'tcx> {
             attr.node.value.hash(&mut state);
         }
 
-        Svh::from_hash(state.finish())
+        Svh::new(state.finish())
     }
 
     fn calculate_item_hash(self, def_id: DefId) -> u64 {
         assert!(def_id.is_local());
 
+        debug!("calculate_item_hash(def_id={:?})", def_id);
+
         let mut state = SipHasher::new();
 
         {
@@ -89,11 +91,16 @@ impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx, 'tcx> {
                 intravisit::walk_crate(&mut visit, krate);
             } else {
                 let node_id = self.map.as_local_node_id(def_id).unwrap();
-                visit.visit_item(self.map.expect_item(node_id));
+                let item = self.map.expect_item(node_id);
+                visit.visit_item(item);
             }
         }
 
-        state.finish()
+        let hash = state.finish();
+
+        debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, hash);
+
+        hash
     }
 }
 
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index d7499342bf5..5e4c9f39e35 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1251,7 +1251,7 @@ pub fn get_crate_deps(data: &[u8]) -> Vec<CrateDep> {
 
     reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| {
         let name = docstr(depdoc, tag_crate_dep_crate_name);
-        let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash));
+        let hash = Svh::new(reader::doc_as_u64(reader::get_doc(depdoc, tag_crate_dep_hash)));
         let doc = reader::get_doc(depdoc, tag_crate_dep_explicitly_linked);
         let explicitly_linked = reader::doc_as_u8(doc) != 0;
         CrateDep {
@@ -1275,14 +1275,14 @@ fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> {
 pub fn maybe_get_crate_hash(data: &[u8]) -> Option<Svh> {
     let cratedoc = rbml::Doc::new(data);
     reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| {
-        Svh::new(doc.as_str_slice().to_string())
+        Svh::new(reader::doc_as_u64(doc))
     })
 }
 
 pub fn get_crate_hash(data: &[u8]) -> Svh {
     let cratedoc = rbml::Doc::new(data);
     let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
-    Svh::new(hashdoc.as_str_slice().to_string())
+    Svh::new(reader::doc_as_u64(hashdoc))
 }
 
 pub fn maybe_get_crate_name(data: &[u8]) -> Option<&str> {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 1b313aac7ca..928601095b0 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1793,14 +1793,14 @@ fn encode_crate_dep(rbml_w: &mut Encoder,
     rbml_w.start_tag(tag_crate_dep);
     rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
     let hash = decoder::get_crate_hash(dep.data());
-    rbml_w.wr_tagged_str(tag_crate_dep_hash, hash.as_str());
+    rbml_w.wr_tagged_u64(tag_crate_dep_hash, hash.as_u64());
     rbml_w.wr_tagged_u8(tag_crate_dep_explicitly_linked,
                         dep.explicitly_linked.get() as u8);
     rbml_w.end_tag();
 }
 
 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
-    rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
+    rbml_w.wr_tagged_u64(tag_crate_hash, hash.as_u64());
 }
 
 fn encode_rustc_version(rbml_w: &mut Encoder) {
diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs
index 4ecb7a28ef7..a5b1c3d301b 100644
--- a/src/librustc_metadata/loader.rs
+++ b/src/librustc_metadata/loader.rs
@@ -620,7 +620,7 @@ impl<'a> Context<'a> {
                 info!("Rejecting via hash: expected {} got {}", *myhash, hash);
                 self.rejected_via_hash.push(CrateMismatch {
                     path: libpath.to_path_buf(),
-                    got: myhash.as_str().to_string()
+                    got: myhash.to_string()
                 });
                 return None;
             }