diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 8a187bb97969a..f59f2bcc07476 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -421,6 +421,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 2f4b0d5c87b0d..665f3de0a3ba7 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 be9284baa74cb..868bc36379135 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -639,25 +639,26 @@ impl<'a> Context<'a> { } fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option { - 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 e11719dc40f2a..32e89f64f0ec1 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,