]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/svh.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / librustc / hir / svh.rs
index 1536f884b0981fc120dc97c243a3fcdae37a7b9f..ae1f9d3028c2c08075934fc18654d212bb7decaa 100644 (file)
 
 //! 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};
+use serialize::{Encodable, Decodable, Encoder, Decoder};
 
-#[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
+    }
 
-        fn hex(b: u64) -> char {
-            let b = (b & 0xf) as u8;
-            let b = match b {
-                0 ... 9 => '0' as u8 + b,
-                _ => 'a' as u8 + b - 10,
-            };
-            b as char
-        }
+    pub fn to_string(&self) -> String {
+        format!("{:016x}", self.hash)
     }
+}
 
-    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())
+    }
+}
+
+impl Encodable for Svh {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_u64(self.as_u64().to_le())
+    }
+}
+
+impl Decodable for Svh {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Svh, D::Error> {
+        d.read_u64()
+         .map(u64::from_le)
+         .map(Svh::new)
     }
 }