From 9699adc508a90834de1c1c432b10f774b8ffcf4f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 28 Sep 2015 07:31:45 +0300 Subject: [PATCH 1/2] store the rustc version in metadata and check it This prevents ICEs when old crates are used with a new version of rustc. Currently, the linking of crates compiled with different versions of rustc is completely unsupported. Fixes #28700 --- src/librustc/diagnostics.rs | 1 + src/librustc/metadata/common.rs | 8 ++++++++ src/librustc/metadata/creader.rs | 21 +++++++++++++++++++++ src/librustc/metadata/decoder.rs | 5 +++++ src/librustc/metadata/encoder.rs | 5 +++++ 5 files changed, 40 insertions(+) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 93c8b2ab0f134..5ed7f4113ec91 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2074,4 +2074,5 @@ register_diagnostics! { E0495, // cannot infer an appropriate lifetime due to conflicting requirements E0496, // .. name `..` shadows a .. name that is already in scope E0498, // malformed plugin attribute + E0514, // metadata version mismatch } diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 0fb55bd790766..bc54d9ff13396 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -259,3 +259,11 @@ pub const tag_defaulted_trait: usize = 0xa4; pub const tag_impl_coerce_unsized_kind: usize = 0xa5; pub const tag_items_data_item_constness: usize = 0xa6; + +pub const tag_rustc_version: usize = 0x10f; +pub fn rustc_version() -> String { + format!( + "rustc {}", + option_env!("CFG_VERSION").unwrap_or("unknown version") + ) +} diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 9acd13f0a0439..3db54320e8522 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -15,6 +15,7 @@ use back::svh::Svh; use session::{config, Session}; use session::search_paths::PathKind; +use metadata::common::rustc_version; use metadata::cstore; use metadata::cstore::{CStore, CrateSource, MetadataBlob}; use metadata::decoder; @@ -270,6 +271,24 @@ impl<'a> CrateReader<'a> { return ret; } + fn verify_rustc_version(&self, + name: &str, + span: Span, + metadata: &MetadataBlob) { + let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice()); + if crate_rustc_version != Some(rustc_version()) { + span_err!(self.sess, span, E0514, + "the crate `{}` has been compiled with {}, which is \ + incompatible with this version of rustc", + name, + crate_rustc_version + .as_ref().map(|s|&**s) + .unwrap_or("an old version of rustc") + ); + self.sess.abort_if_errors(); + } + } + fn register_crate(&mut self, root: &Option, ident: &str, @@ -279,6 +298,8 @@ impl<'a> CrateReader<'a> { explicitly_linked: bool) -> (ast::CrateNum, Rc, cstore::CrateSource) { + self.verify_rustc_version(name, span, &lib.metadata); + // Claim this crate number and cache it let cnum = self.next_crate_num; self.next_crate_num += 1; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 050e04bff8307..648ebdefffe6c 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -77,6 +77,11 @@ pub fn load_index(data: &[u8]) -> index::Index { index::Index::from_buf(index.data, index.start, index.end) } +pub fn crate_rustc_version(data: &[u8]) -> Option { + let doc = rbml::Doc::new(data); + reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str()) +} + #[derive(Debug, PartialEq)] enum Family { ImmStatic, // c diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8addc06c8840d..8acdc7e8ce2ba 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1923,6 +1923,10 @@ fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) { rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str()); } +fn encode_rustc_version(rbml_w: &mut Encoder) { + rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version()); +} + fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) { rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name); } @@ -2051,6 +2055,7 @@ fn encode_metadata_inner(wr: &mut Cursor>, let mut rbml_w = Encoder::new(wr); + encode_rustc_version(&mut rbml_w); encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name); encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple); encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash); From f2d5ebeae94c78799b4e4d2f8fd5c526df87e949 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 30 Sep 2015 00:51:12 +0300 Subject: [PATCH 2/2] sacrifice a few bytes for the euv demon --- src/librustc/middle/expr_use_visitor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 9a5b21be72892..13e8fddf77912 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -244,7 +244,7 @@ impl OverloadedCallType { // can just use the tcx as the typer. // // FIXME(stage0): the :'t here is probably only important for stage0 -pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d+'t> { +pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> { typer: &'t infer::InferCtxt<'a, 'tcx>, mc: mc::MemCategorizationContext<'t, 'a, 'tcx>, delegate: &'d mut Delegate<'tcx>, @@ -278,7 +278,7 @@ enum PassArgs { impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { pub fn new(delegate: &'d mut Delegate<'tcx>, typer: &'t infer::InferCtxt<'a, 'tcx>) - -> ExprUseVisitor<'d,'t,'a,'tcx> + -> ExprUseVisitor<'d,'t,'a,'tcx> where 'tcx:'a { ExprUseVisitor { typer: typer,