about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2016-11-22 14:51:55 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2016-11-22 14:51:55 +0200
commitf4c68d2825535cbef847d0ac874ceced81cf2980 (patch)
tree35b3cbf1433d8354094884df75bd74f39297ba57
parent1c11ea3aedebac562f5125e1cf22ac56a3a8993c (diff)
downloadrust-f4c68d2825535cbef847d0ac874ceced81cf2980.tar.gz
rust-f4c68d2825535cbef847d0ac874ceced81cf2980.zip
rustc_metadata: don't break the version check when CrateRoot changes.
-rw-r--r--src/librustc_metadata/decoder.rs4
-rw-r--r--src/librustc_metadata/encoder.rs15
-rw-r--r--src/librustc_metadata/locator.rs21
-rw-r--r--src/librustc_metadata/schema.rs9
4 files changed, 31 insertions, 18 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index fb1314992c0..25045679e71 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -420,6 +420,10 @@ impl<'a, 'tcx> MetadataBlob {
         self.raw_bytes().starts_with(METADATA_HEADER)
     }
 
+    pub fn get_rustc_version(&self) -> String {
+        Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
+    }
+
     pub fn get_root(&self) -> CrateRoot {
         let slice = self.raw_bytes();
         let offset = METADATA_HEADER.len();
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 2f4b0d5c87b..665f3de0a3b 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1278,7 +1278,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let link_meta = self.link_meta;
         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
         let root = self.lazy(&CrateRoot {
-            rustc_version: rustc_version(),
             name: link_meta.crate_name,
             triple: tcx.sess.opts.target_triple.clone(),
             hash: link_meta.crate_hash,
@@ -1368,7 +1367,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Will be filed with the root position after encoding everything.
     cursor.write_all(&[0, 0, 0, 0]).unwrap();
 
-    let root = EncodeContext {
+    let root = {
+        let mut ecx = EncodeContext {
             opaque: opaque::Encoder::new(&mut cursor),
             tcx: tcx,
             reexports: reexports,
@@ -1378,8 +1378,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
-        }
-        .encode_crate_root();
+        };
+
+        // Encode the rustc version string in a predictable location.
+        rustc_version().encode(&mut ecx).unwrap();
+
+        // Encode all the entries and extra information in the crate,
+        // culminating in the `CrateRoot` which points to all of it.
+        ecx.encode_crate_root()
+    };
     let mut result = cursor.into_inner();
 
     // Encode the root position.
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index f5196f7ea84..106d479c12c 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -629,25 +629,26 @@ impl<'a> Context<'a> {
     }
 
     fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
-        let root = metadata.get_root();
-        if let Some(is_proc_macro) = self.is_proc_macro {
-            if root.macro_derive_registrar.is_some() != is_proc_macro {
-                return None;
-            }
-        }
-
         let rustc_version = rustc_version();
-        if root.rustc_version != rustc_version {
+        let found_version = metadata.get_rustc_version();
+        if found_version != rustc_version {
             info!("Rejecting via version: expected {} got {}",
                   rustc_version,
-                  root.rustc_version);
+                  found_version);
             self.rejected_via_version.push(CrateMismatch {
                 path: libpath.to_path_buf(),
-                got: root.rustc_version,
+                got: found_version,
             });
             return None;
         }
 
+        let root = metadata.get_root();
+        if let Some(is_proc_macro) = self.is_proc_macro {
+            if root.macro_derive_registrar.is_some() != is_proc_macro {
+                return None;
+            }
+        }
+
         if self.should_match_name {
             if self.crate_name != root.name {
                 info!("Rejecting via crate name");
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index e11719dc40f..32e89f64f0e 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -34,15 +34,17 @@ pub fn rustc_version() -> String {
 
 /// Metadata encoding version.
 /// NB: increment this if you change the format of metadata such that
-/// the rustc version can't be found to compare with `RUSTC_VERSION`.
-pub const METADATA_VERSION: u8 = 3;
+/// the rustc version can't be found to compare with `rustc_version()`.
+pub const METADATA_VERSION: u8 = 4;
 
 /// Metadata header which includes `METADATA_VERSION`.
 /// To get older versions of rustc to ignore this metadata,
 /// there are 4 zero bytes at the start, which are treated
 /// as a length of 0 by old compilers.
 ///
-/// This header is followed by the position of the `CrateRoot`.
+/// This header is followed by the position of the `CrateRoot`,
+/// which is encoded as a 32-bit big-endian unsigned integer,
+/// and further followed by the rustc version string.
 pub const METADATA_HEADER: &'static [u8; 12] =
     &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
@@ -163,7 +165,6 @@ pub enum LazyState {
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct CrateRoot {
-    pub rustc_version: String,
     pub name: Symbol,
     pub triple: String,
     pub hash: hir::svh::Svh,