Skip to content

Commit 9699adc

Browse files
author
Ariel Ben-Yehuda
committed
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
1 parent 5f06607 commit 9699adc

File tree

5 files changed

+40
-0
lines changed

5 files changed

+40
-0
lines changed

src/librustc/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2074,4 +2074,5 @@ register_diagnostics! {
20742074
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
20752075
E0496, // .. name `..` shadows a .. name that is already in scope
20762076
E0498, // malformed plugin attribute
2077+
E0514, // metadata version mismatch
20772078
}

src/librustc/metadata/common.rs

+8
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,11 @@ pub const tag_defaulted_trait: usize = 0xa4;
259259
pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
260260

261261
pub const tag_items_data_item_constness: usize = 0xa6;
262+
263+
pub const tag_rustc_version: usize = 0x10f;
264+
pub fn rustc_version() -> String {
265+
format!(
266+
"rustc {}",
267+
option_env!("CFG_VERSION").unwrap_or("unknown version")
268+
)
269+
}

src/librustc/metadata/creader.rs

+21
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use back::svh::Svh;
1616
use session::{config, Session};
1717
use session::search_paths::PathKind;
18+
use metadata::common::rustc_version;
1819
use metadata::cstore;
1920
use metadata::cstore::{CStore, CrateSource, MetadataBlob};
2021
use metadata::decoder;
@@ -270,6 +271,24 @@ impl<'a> CrateReader<'a> {
270271
return ret;
271272
}
272273

274+
fn verify_rustc_version(&self,
275+
name: &str,
276+
span: Span,
277+
metadata: &MetadataBlob) {
278+
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
279+
if crate_rustc_version != Some(rustc_version()) {
280+
span_err!(self.sess, span, E0514,
281+
"the crate `{}` has been compiled with {}, which is \
282+
incompatible with this version of rustc",
283+
name,
284+
crate_rustc_version
285+
.as_ref().map(|s|&**s)
286+
.unwrap_or("an old version of rustc")
287+
);
288+
self.sess.abort_if_errors();
289+
}
290+
}
291+
273292
fn register_crate(&mut self,
274293
root: &Option<CratePaths>,
275294
ident: &str,
@@ -279,6 +298,8 @@ impl<'a> CrateReader<'a> {
279298
explicitly_linked: bool)
280299
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
281300
cstore::CrateSource) {
301+
self.verify_rustc_version(name, span, &lib.metadata);
302+
282303
// Claim this crate number and cache it
283304
let cnum = self.next_crate_num;
284305
self.next_crate_num += 1;

src/librustc/metadata/decoder.rs

+5
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ pub fn load_index(data: &[u8]) -> index::Index {
7777
index::Index::from_buf(index.data, index.start, index.end)
7878
}
7979

80+
pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
81+
let doc = rbml::Doc::new(data);
82+
reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str())
83+
}
84+
8085
#[derive(Debug, PartialEq)]
8186
enum Family {
8287
ImmStatic, // c

src/librustc/metadata/encoder.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1923,6 +1923,10 @@ fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
19231923
rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
19241924
}
19251925

1926+
fn encode_rustc_version(rbml_w: &mut Encoder) {
1927+
rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version());
1928+
}
1929+
19261930
fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
19271931
rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
19281932
}
@@ -2051,6 +2055,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
20512055

20522056
let mut rbml_w = Encoder::new(wr);
20532057

2058+
encode_rustc_version(&mut rbml_w);
20542059
encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
20552060
encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
20562061
encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);

0 commit comments

Comments
 (0)