Auto merge of #28702 - arielb1:metadata-versioning, r=nrc
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 r? @nrc
This commit is contained in:
@@ -2074,4 +2074,5 @@ register_diagnostics! {
|
|||||||
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
|
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
|
||||||
E0496, // .. name `..` shadows a .. name that is already in scope
|
E0496, // .. name `..` shadows a .. name that is already in scope
|
||||||
E0498, // malformed plugin attribute
|
E0498, // malformed plugin attribute
|
||||||
|
E0514, // metadata version mismatch
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,3 +259,11 @@ pub const tag_defaulted_trait: usize = 0xa4;
|
|||||||
pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
|
pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
|
||||||
|
|
||||||
pub const tag_items_data_item_constness: usize = 0xa6;
|
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")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use back::svh::Svh;
|
use back::svh::Svh;
|
||||||
use session::{config, Session};
|
use session::{config, Session};
|
||||||
use session::search_paths::PathKind;
|
use session::search_paths::PathKind;
|
||||||
|
use metadata::common::rustc_version;
|
||||||
use metadata::cstore;
|
use metadata::cstore;
|
||||||
use metadata::cstore::{CStore, CrateSource, MetadataBlob};
|
use metadata::cstore::{CStore, CrateSource, MetadataBlob};
|
||||||
use metadata::decoder;
|
use metadata::decoder;
|
||||||
@@ -270,6 +271,24 @@ impl<'a> CrateReader<'a> {
|
|||||||
return ret;
|
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,
|
fn register_crate(&mut self,
|
||||||
root: &Option<CratePaths>,
|
root: &Option<CratePaths>,
|
||||||
ident: &str,
|
ident: &str,
|
||||||
@@ -279,6 +298,8 @@ impl<'a> CrateReader<'a> {
|
|||||||
explicitly_linked: bool)
|
explicitly_linked: bool)
|
||||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||||
cstore::CrateSource) {
|
cstore::CrateSource) {
|
||||||
|
self.verify_rustc_version(name, span, &lib.metadata);
|
||||||
|
|
||||||
// Claim this crate number and cache it
|
// Claim this crate number and cache it
|
||||||
let cnum = self.next_crate_num;
|
let cnum = self.next_crate_num;
|
||||||
self.next_crate_num += 1;
|
self.next_crate_num += 1;
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ pub fn load_index(data: &[u8]) -> index::Index {
|
|||||||
index::Index::from_buf(index.data, index.start, index.end)
|
index::Index::from_buf(index.data, index.start, index.end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
|
||||||
|
let doc = rbml::Doc::new(data);
|
||||||
|
reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum Family {
|
enum Family {
|
||||||
ImmStatic, // c
|
ImmStatic, // c
|
||||||
|
|||||||
@@ -1923,6 +1923,10 @@ fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
|
|||||||
rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
|
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) {
|
fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
|
||||||
rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
|
rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
|
||||||
}
|
}
|
||||||
@@ -2051,6 +2055,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
|
|||||||
|
|
||||||
let mut rbml_w = Encoder::new(wr);
|
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_name(&mut rbml_w, &ecx.link_meta.crate_name);
|
||||||
encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
|
encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
|
||||||
encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
|
encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ impl OverloadedCallType {
|
|||||||
// can just use the tcx as the typer.
|
// can just use the tcx as the typer.
|
||||||
//
|
//
|
||||||
// FIXME(stage0): the :'t here is probably only important for stage0
|
// 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>,
|
typer: &'t infer::InferCtxt<'a, 'tcx>,
|
||||||
mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
|
mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
|
||||||
delegate: &'d mut Delegate<'tcx>,
|
delegate: &'d mut Delegate<'tcx>,
|
||||||
@@ -278,7 +278,7 @@ enum PassArgs {
|
|||||||
impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
|
impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
|
||||||
pub fn new(delegate: &'d mut Delegate<'tcx>,
|
pub fn new(delegate: &'d mut Delegate<'tcx>,
|
||||||
typer: &'t infer::InferCtxt<'a, 'tcx>)
|
typer: &'t infer::InferCtxt<'a, 'tcx>)
|
||||||
-> ExprUseVisitor<'d,'t,'a,'tcx>
|
-> ExprUseVisitor<'d,'t,'a,'tcx> where 'tcx:'a
|
||||||
{
|
{
|
||||||
ExprUseVisitor {
|
ExprUseVisitor {
|
||||||
typer: typer,
|
typer: typer,
|
||||||
|
|||||||
Reference in New Issue
Block a user