Make the compiler emit an error if the crate graph contains two crates with the same crate-name and crate-salt but different SVHs.
This commit is contained in:
parent
fafdfa8bdc
commit
2eebb7b605
22 changed files with 103 additions and 24 deletions
|
|
@ -526,11 +526,15 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||
|
||||
let macros = time(time_passes,
|
||||
"macro loading",
|
||||
|| macro_import::read_macro_defs(sess, &cstore, &krate));
|
||||
|| macro_import::read_macro_defs(sess, &cstore, &krate, crate_name));
|
||||
|
||||
let mut addl_plugins = Some(addl_plugins);
|
||||
let registrars = time(time_passes, "plugin loading", || {
|
||||
plugin::load::load_plugins(sess, &cstore, &krate, addl_plugins.take().unwrap())
|
||||
plugin::load::load_plugins(sess,
|
||||
&cstore,
|
||||
&krate,
|
||||
crate_name,
|
||||
addl_plugins.take().unwrap())
|
||||
});
|
||||
|
||||
let mut registry = Registry::new(sess, &krate);
|
||||
|
|
@ -755,7 +759,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||
|
||||
time(time_passes,
|
||||
"external crate/lib resolution",
|
||||
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates());
|
||||
|| LocalCrateReader::new(sess, cstore, &hir_map, name).read_crates());
|
||||
|
||||
let lang_items = time(time_passes, "language item collection", || {
|
||||
sess.track_errors(|| {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ pub struct CrateReader<'a> {
|
|||
cstore: &'a CStore,
|
||||
next_crate_num: ast::CrateNum,
|
||||
foreign_item_map: FnvHashMap<String, Vec<ast::NodeId>>,
|
||||
local_crate_name: String,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'hir> Visitor<'hir> for LocalCrateReader<'a, 'b> {
|
||||
|
|
@ -146,12 +147,15 @@ impl PMDSource {
|
|||
}
|
||||
|
||||
impl<'a> CrateReader<'a> {
|
||||
pub fn new(sess: &'a Session, cstore: &'a CStore) -> CrateReader<'a> {
|
||||
pub fn new(sess: &'a Session,
|
||||
cstore: &'a CStore,
|
||||
local_crate_name: &str) -> CrateReader<'a> {
|
||||
CrateReader {
|
||||
sess: sess,
|
||||
cstore: cstore,
|
||||
next_crate_num: cstore.next_crate_num(),
|
||||
foreign_item_map: FnvHashMap(),
|
||||
local_crate_name: local_crate_name.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,6 +276,38 @@ impl<'a> CrateReader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn verify_no_symbol_conflicts(&self,
|
||||
crate_name: &str,
|
||||
span: Span,
|
||||
metadata: &MetadataBlob) {
|
||||
let disambiguator = decoder::get_crate_disambiguator(metadata.as_slice());
|
||||
|
||||
// Check for (potential) conflicts with the local crate
|
||||
if self.local_crate_name == crate_name &&
|
||||
&self.sess.crate_disambiguator.borrow()[..] == disambiguator {
|
||||
span_fatal!(self.sess, span, E0519,
|
||||
"the current crate is indistinguishable from one of its \
|
||||
dependencies: it has the same crate-name `{}` and was \
|
||||
compiled with the same `-C metadata` arguments. This \
|
||||
will result in symbol conflicts between the two.",
|
||||
crate_name)
|
||||
}
|
||||
|
||||
let svh = decoder::get_crate_hash(metadata.as_slice());
|
||||
// Check for conflicts with any crate loaded so far
|
||||
self.cstore.iter_crate_data(|_, other| {
|
||||
if other.name() == crate_name && // same crate-name
|
||||
other.disambiguator() == disambiguator && // same crate-disambiguator
|
||||
other.hash() != svh { // but different SVH
|
||||
span_fatal!(self.sess, span, E0520,
|
||||
"found two different crates with name `{}` that are \
|
||||
not distinguished by differing `-C metadata`. This \
|
||||
will result in symbol conflicts between the two.",
|
||||
crate_name)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn register_crate(&mut self,
|
||||
root: &Option<CratePaths>,
|
||||
ident: &str,
|
||||
|
|
@ -282,6 +318,7 @@ impl<'a> CrateReader<'a> {
|
|||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||
cstore::CrateSource) {
|
||||
self.verify_rustc_version(name, span, &lib.metadata);
|
||||
self.verify_no_symbol_conflicts(name, span, &lib.metadata);
|
||||
|
||||
// Claim this crate number and cache it
|
||||
let cnum = self.next_crate_num;
|
||||
|
|
@ -713,12 +750,15 @@ impl<'a> CrateReader<'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'b> LocalCrateReader<'a, 'b> {
|
||||
pub fn new(sess: &'a Session, cstore: &'a CStore,
|
||||
map: &'a hir_map::Map<'b>) -> LocalCrateReader<'a, 'b> {
|
||||
pub fn new(sess: &'a Session,
|
||||
cstore: &'a CStore,
|
||||
map: &'a hir_map::Map<'b>,
|
||||
local_crate_name: &str)
|
||||
-> LocalCrateReader<'a, 'b> {
|
||||
LocalCrateReader {
|
||||
sess: sess,
|
||||
cstore: cstore,
|
||||
creader: CrateReader::new(sess, cstore),
|
||||
creader: CrateReader::new(sess, cstore, local_crate_name),
|
||||
ast_map: map,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,9 @@ impl crate_metadata {
|
|||
pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
|
||||
pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
|
||||
pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
|
||||
pub fn disambiguator(&self) -> &str {
|
||||
decoder::get_crate_disambiguator(self.data())
|
||||
}
|
||||
pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
|
||||
-> Ref<'a, Vec<ImportedFileMap>> {
|
||||
let filemaps = self.codemap_import_info.borrow();
|
||||
|
|
|
|||
|
|
@ -1297,8 +1297,8 @@ pub fn maybe_get_crate_name(data: &[u8]) -> Option<String> {
|
|||
|
||||
pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
|
||||
let crate_doc = rbml::Doc::new(data);
|
||||
let salt_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
|
||||
let slice: &'a str = salt_doc.as_str_slice();
|
||||
let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
|
||||
let slice: &'a str = disambiguator_doc.as_str_slice();
|
||||
slice
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,4 +87,6 @@ register_diagnostics! {
|
|||
E0468, // an `extern crate` loading macros must be at the crate root
|
||||
E0469, // imported macro not found
|
||||
E0470, // reexported macro not found
|
||||
E0519, // local crate and dependency have same (crate-name, disambiguator)
|
||||
E0520, // two dependencies have same (crate-name, disambiguator) but different SVH
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ struct MacroLoader<'a> {
|
|||
}
|
||||
|
||||
impl<'a> MacroLoader<'a> {
|
||||
fn new(sess: &'a Session, cstore: &'a CStore) -> MacroLoader<'a> {
|
||||
fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> MacroLoader<'a> {
|
||||
MacroLoader {
|
||||
sess: sess,
|
||||
span_whitelist: HashSet::new(),
|
||||
reader: CrateReader::new(sess, cstore),
|
||||
reader: CrateReader::new(sess, cstore, crate_name),
|
||||
macros: vec![],
|
||||
}
|
||||
}
|
||||
|
|
@ -47,10 +47,13 @@ pub fn call_bad_macro_reexport(a: &Session, b: Span) {
|
|||
}
|
||||
|
||||
/// Read exported macros.
|
||||
pub fn read_macro_defs(sess: &Session, cstore: &CStore, krate: &ast::Crate)
|
||||
pub fn read_macro_defs(sess: &Session,
|
||||
cstore: &CStore,
|
||||
krate: &ast::Crate,
|
||||
crate_name: &str)
|
||||
-> Vec<ast::MacroDef>
|
||||
{
|
||||
let mut loader = MacroLoader::new(sess, cstore);
|
||||
let mut loader = MacroLoader::new(sess, cstore, crate_name);
|
||||
|
||||
// We need to error on `#[macro_use] extern crate` when it isn't at the
|
||||
// crate root, because `$crate` won't work properly. Identify these by
|
||||
|
|
|
|||
|
|
@ -44,9 +44,12 @@ fn call_malformed_plugin_attribute(a: &Session, b: Span) {
|
|||
}
|
||||
|
||||
/// Read plugin metadata and dynamically load registrar functions.
|
||||
pub fn load_plugins(sess: &Session, cstore: &CStore, krate: &ast::Crate,
|
||||
pub fn load_plugins(sess: &Session,
|
||||
cstore: &CStore,
|
||||
krate: &ast::Crate,
|
||||
crate_name: &str,
|
||||
addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
|
||||
let mut loader = PluginLoader::new(sess, cstore);
|
||||
let mut loader = PluginLoader::new(sess, cstore, crate_name);
|
||||
|
||||
for attr in &krate.attrs {
|
||||
if !attr.check_name("plugin") {
|
||||
|
|
@ -82,10 +85,10 @@ pub fn load_plugins(sess: &Session, cstore: &CStore, krate: &ast::Crate,
|
|||
}
|
||||
|
||||
impl<'a> PluginLoader<'a> {
|
||||
fn new(sess: &'a Session, cstore: &'a CStore) -> PluginLoader<'a> {
|
||||
fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> PluginLoader<'a> {
|
||||
PluginLoader {
|
||||
sess: sess,
|
||||
reader: CrateReader::new(sess, cstore),
|
||||
reader: CrateReader::new(sess, cstore, crate_name),
|
||||
plugins: vec![],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,11 +78,12 @@
|
|||
//!
|
||||
//! - In order to be able to also use symbols from two versions of the same
|
||||
//! crate (which naturally also have the same name), a stronger measure is
|
||||
//! required: The compiler accepts an arbitrary "salt" value via the
|
||||
//! `-C metadata` commandline argument. This salt is then fed into the symbol
|
||||
//! hash of every exported item. Consequently, the symbols in two identical
|
||||
//! crates but with different salts are not in conflict with each other. This
|
||||
//! facility is mainly intended to be used by build tools like Cargo.
|
||||
//! required: The compiler accepts an arbitrary "disambiguator" value via the
|
||||
//! `-C metadata` commandline argument. This disambiguator is then fed into
|
||||
//! the symbol hash of every exported item. Consequently, the symbols in two
|
||||
//! identical crates but with different disambiguators are not in conflict
|
||||
//! with each other. This facility is mainly intended to be used by build
|
||||
//! tools like Cargo.
|
||||
//!
|
||||
//! A note on symbol name stability
|
||||
//! -------------------------------
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub trait Foo {
|
||||
fn bar(&self);
|
||||
fn foo(&mut self) {}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub trait Foo {
|
||||
#[doc(hidden)]
|
||||
fn foo(&self) {}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
#![doc(html_root_url = "http://example.com/")]
|
||||
|
||||
/// dox
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
#![doc(html_root_url = "http://example.com")]
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
pub struct Foo;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub trait Trait {
|
||||
type Output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub trait Deref {
|
||||
type Target: ?Sized;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub trait Foo {
|
||||
type Bar;
|
||||
fn foo(&self) {}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
impl Foo {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub mod foo {
|
||||
|
||||
pub trait Foo {}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
#![feature(const_fn)]
|
||||
|
||||
pub const fn foo() {}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Cmetadata=aux
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
#[doc(hidden)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) libc.rs
|
||||
$(RUSTC) libc.rs -Cmetadata=foo
|
||||
$(RUSTC) main.rs --extern libc=$(TMPDIR)/liblibc.rlib
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ time: libc
|
|||
|
||||
libc:
|
||||
mkdir -p $(OUT)/libc
|
||||
$(RUSTC) in/libc/lib.rs --crate-name=libc -o $(OUT)/libc/liblibc.rlib
|
||||
$(RUSTC) in/libc/lib.rs --crate-name=libc -Cmetadata=foo -o $(OUT)/libc/liblibc.rlib
|
||||
else
|
||||
all:
|
||||
endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue