Skip to content

Commit 9d5ce13

Browse files
Make the compiler emit an error if the crate graph contains two crates with the same crate-name and crate-salt but different SVHs.
1 parent 25cbff1 commit 9d5ce13

22 files changed

+107
-28
lines changed

src/librustc_driver/driver.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,11 +526,15 @@ pub fn phase_2_configure_and_expand(sess: &Session,
526526

527527
let macros = time(time_passes,
528528
"macro loading",
529-
|| macro_import::read_macro_defs(sess, &cstore, &krate));
529+
|| macro_import::read_macro_defs(sess, &cstore, &krate, crate_name));
530530

531531
let mut addl_plugins = Some(addl_plugins);
532532
let registrars = time(time_passes, "plugin loading", || {
533-
plugin::load::load_plugins(sess, &cstore, &krate, addl_plugins.take().unwrap())
533+
plugin::load::load_plugins(sess,
534+
&cstore,
535+
&krate,
536+
crate_name,
537+
addl_plugins.take().unwrap())
534538
});
535539

536540
let mut registry = Registry::new(sess, &krate);
@@ -755,7 +759,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
755759

756760
time(time_passes,
757761
"external crate/lib resolution",
758-
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates());
762+
|| LocalCrateReader::new(sess, cstore, &hir_map, name).read_crates());
759763

760764
let lang_items = try!(time(time_passes, "language item collection", || {
761765
sess.track_errors(|| {

src/librustc_metadata/creader.rs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct CrateReader<'a> {
5555
cstore: &'a CStore,
5656
next_crate_num: ast::CrateNum,
5757
foreign_item_map: FnvHashMap<String, Vec<ast::NodeId>>,
58+
local_crate_name: String,
5859
}
5960

6061
impl<'a, 'b, 'hir> Visitor<'hir> for LocalCrateReader<'a, 'b> {
@@ -146,12 +147,15 @@ impl PMDSource {
146147
}
147148

148149
impl<'a> CrateReader<'a> {
149-
pub fn new(sess: &'a Session, cstore: &'a CStore) -> CrateReader<'a> {
150+
pub fn new(sess: &'a Session,
151+
cstore: &'a CStore,
152+
local_crate_name: &str) -> CrateReader<'a> {
150153
CrateReader {
151154
sess: sess,
152155
cstore: cstore,
153156
next_crate_num: cstore.next_crate_num(),
154157
foreign_item_map: FnvHashMap(),
158+
local_crate_name: local_crate_name.to_owned(),
155159
}
156160
}
157161

@@ -272,6 +276,38 @@ impl<'a> CrateReader<'a> {
272276
}
273277
}
274278

279+
fn verify_no_symbol_conflicts(&self,
280+
crate_name: &str,
281+
span: Span,
282+
metadata: &MetadataBlob) {
283+
let disambiguator = decoder::get_crate_disambiguator(metadata.as_slice());
284+
285+
// Check for (potential) conflicts with the local crate
286+
if self.local_crate_name == crate_name &&
287+
&self.sess.crate_disambiguator.borrow()[..] == disambiguator {
288+
span_fatal!(self.sess, span, E0519,
289+
"the current crate is indistinguishable from one of its \
290+
dependencies: it has the same crate-name `{}` and was \
291+
compiled with the same `-C metadata` arguments. This \
292+
will result in symbol conflicts between the two.",
293+
crate_name)
294+
}
295+
296+
let svh = decoder::get_crate_hash(metadata.as_slice());
297+
// Check for conflicts with any crate loaded so far
298+
self.cstore.iter_crate_data(|_, other| {
299+
if other.name() == crate_name && // same crate-name
300+
other.disambiguator() == disambiguator && // same crate-disambiguator
301+
other.hash() != svh { // but different SVH
302+
span_fatal!(self.sess, span, E0520,
303+
"found two different crates with name `{}` that are \
304+
not distinguished by differing `-C metadata`. This \
305+
will result in symbol conflicts between the two.",
306+
crate_name)
307+
}
308+
});
309+
}
310+
275311
fn register_crate(&mut self,
276312
root: &Option<CratePaths>,
277313
ident: &str,
@@ -282,6 +318,7 @@ impl<'a> CrateReader<'a> {
282318
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
283319
cstore::CrateSource) {
284320
self.verify_rustc_version(name, span, &lib.metadata);
321+
self.verify_no_symbol_conflicts(name, span, &lib.metadata);
285322

286323
// Claim this crate number and cache it
287324
let cnum = self.next_crate_num;
@@ -713,12 +750,15 @@ impl<'a> CrateReader<'a> {
713750
}
714751

715752
impl<'a, 'b> LocalCrateReader<'a, 'b> {
716-
pub fn new(sess: &'a Session, cstore: &'a CStore,
717-
map: &'a hir_map::Map<'b>) -> LocalCrateReader<'a, 'b> {
753+
pub fn new(sess: &'a Session,
754+
cstore: &'a CStore,
755+
map: &'a hir_map::Map<'b>,
756+
local_crate_name: &str)
757+
-> LocalCrateReader<'a, 'b> {
718758
LocalCrateReader {
719759
sess: sess,
720760
cstore: cstore,
721-
creader: CrateReader::new(sess, cstore),
761+
creader: CrateReader::new(sess, cstore, local_crate_name),
722762
ast_map: map,
723763
}
724764
}

src/librustc_metadata/cstore.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ impl crate_metadata {
250250
pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
251251
pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
252252
pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
253+
pub fn disambiguator(&self) -> &str {
254+
decoder::get_crate_disambiguator(self.data())
255+
}
253256
pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
254257
-> Ref<'a, Vec<ImportedFileMap>> {
255258
let filemaps = self.codemap_import_info.borrow();

src/librustc_metadata/decoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,8 +1320,8 @@ pub fn maybe_get_crate_name(data: &[u8]) -> Option<String> {
13201320

13211321
pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
13221322
let crate_doc = rbml::Doc::new(data);
1323-
let salt_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
1324-
let slice: &'a str = salt_doc.as_str_slice();
1323+
let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
1324+
let slice: &'a str = disambiguator_doc.as_str_slice();
13251325
slice
13261326
}
13271327

src/librustc_metadata/diagnostics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,6 @@ register_diagnostics! {
8787
E0468, // an `extern crate` loading macros must be at the crate root
8888
E0469, // imported macro not found
8989
E0470, // reexported macro not found
90+
E0519, // local crate and dependency have same (crate-name, disambiguator)
91+
E0520, // two dependencies have same (crate-name, disambiguator) but different SVH
9092
}

src/librustc_metadata/macro_import.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ struct MacroLoader<'a> {
3232
}
3333

3434
impl<'a> MacroLoader<'a> {
35-
fn new(sess: &'a Session, cstore: &'a CStore) -> MacroLoader<'a> {
35+
fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> MacroLoader<'a> {
3636
MacroLoader {
3737
sess: sess,
3838
span_whitelist: HashSet::new(),
39-
reader: CrateReader::new(sess, cstore),
39+
reader: CrateReader::new(sess, cstore, crate_name),
4040
macros: vec![],
4141
}
4242
}
@@ -47,10 +47,13 @@ pub fn call_bad_macro_reexport(a: &Session, b: Span) {
4747
}
4848

4949
/// Read exported macros.
50-
pub fn read_macro_defs(sess: &Session, cstore: &CStore, krate: &ast::Crate)
50+
pub fn read_macro_defs(sess: &Session,
51+
cstore: &CStore,
52+
krate: &ast::Crate,
53+
crate_name: &str)
5154
-> Vec<ast::MacroDef>
5255
{
53-
let mut loader = MacroLoader::new(sess, cstore);
56+
let mut loader = MacroLoader::new(sess, cstore, crate_name);
5457

5558
// We need to error on `#[macro_use] extern crate` when it isn't at the
5659
// crate root, because `$crate` won't work properly. Identify these by

src/librustc_plugin/load.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ fn call_malformed_plugin_attribute(a: &Session, b: Span) {
4444
}
4545

4646
/// Read plugin metadata and dynamically load registrar functions.
47-
pub fn load_plugins(sess: &Session, cstore: &CStore, krate: &ast::Crate,
47+
pub fn load_plugins(sess: &Session,
48+
cstore: &CStore,
49+
krate: &ast::Crate,
50+
crate_name: &str,
4851
addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
49-
let mut loader = PluginLoader::new(sess, cstore);
52+
let mut loader = PluginLoader::new(sess, cstore, crate_name);
5053

5154
for attr in &krate.attrs {
5255
if !attr.check_name("plugin") {
@@ -82,10 +85,10 @@ pub fn load_plugins(sess: &Session, cstore: &CStore, krate: &ast::Crate,
8285
}
8386

8487
impl<'a> PluginLoader<'a> {
85-
fn new(sess: &'a Session, cstore: &'a CStore) -> PluginLoader<'a> {
88+
fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> PluginLoader<'a> {
8689
PluginLoader {
8790
sess: sess,
88-
reader: CrateReader::new(sess, cstore),
91+
reader: CrateReader::new(sess, cstore, crate_name),
8992
plugins: vec![],
9093
}
9194
}

src/librustc_trans/back/symbol_names.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@
7878
//!
7979
//! - In order to be able to also use symbols from two versions of the same
8080
//! crate (which naturally also have the same name), a stronger measure is
81-
//! required: The compiler accepts an arbitrary "salt" value via the
82-
//! `-C metadata` commandline argument. This salt is then fed into the symbol
83-
//! hash of every exported item. Consequently, the symbols in two identical
84-
//! crates but with different salts are not in conflict with each other. This
85-
//! facility is mainly intended to be used by build tools like Cargo.
81+
//! required: The compiler accepts an arbitrary "disambiguator" value via the
82+
//! `-C metadata` commandline argument. This disambiguator is then fed into
83+
//! the symbol hash of every exported item. Consequently, the symbols in two
84+
//! identical crates but with different disambiguators are not in conflict
85+
//! with each other. This facility is mainly intended to be used by build
86+
//! tools like Cargo.
8687
//!
8788
//! A note on symbol name stability
8889
//! -------------------------------
@@ -118,12 +119,12 @@ pub fn def_id_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_id: DefId) -> String {
118119
let def_path = if def_id.is_local() {
119120
s.push_str(&tcx.crate_name[..]);
120121
s.push_str("/");
121-
s.push_str(&tcx.sess.crate_salt.borrow()[..]);
122+
s.push_str(&tcx.sess.crate_disambiguator.borrow()[..]);
122123
&def_path[..]
123124
} else {
124125
s.push_str(&tcx.sess.cstore.crate_name(def_id.krate)[..]);
125126
s.push_str("/");
126-
s.push_str(&tcx.sess.cstore.crate_salt(def_id.krate));
127+
s.push_str(&tcx.sess.cstore.crate_disambiguator(def_id.krate));
127128
&def_path[1..]
128129
};
129130

@@ -150,9 +151,9 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
150151
hash_state.reset();
151152

152153
if originating_crate == cstore::LOCAL_CRATE {
153-
hash_state.input_str(&tcx.sess.crate_salt.borrow()[..]);
154+
hash_state.input_str(&tcx.sess.crate_disambiguator.borrow()[..]);
154155
} else {
155-
hash_state.input_str(&tcx.sess.cstore.crate_salt(originating_crate));
156+
hash_state.input_str(&tcx.sess.cstore.crate_disambiguator(originating_crate));
156157
}
157158

158159
for component in def_path {

src/test/auxiliary/inline-default-methods.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub trait Foo {
1214
fn bar(&self);
1315
fn foo(&mut self) {}

src/test/auxiliary/issue-13698.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub trait Foo {
1214
#[doc(hidden)]
1315
fn foo(&self) {}

src/test/auxiliary/issue-15318.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
#![doc(html_root_url = "http://example.com/")]
1214

1315
/// dox

src/test/auxiliary/issue-17476.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
1112

1213
#![doc(html_root_url = "http://example.com")]
1314

src/test/auxiliary/issue-19190-3.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
use std::ops::Deref;
1214

1315
pub struct Foo;

src/test/auxiliary/issue-20646.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub trait Trait {
1214
type Output;
1315
}

src/test/auxiliary/issue-20727.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub trait Deref {
1214
type Target: ?Sized;
1315

src/test/auxiliary/issue-21092.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub trait Foo {
1214
type Bar;
1315
fn foo(&self) {}

src/test/auxiliary/issue-21801.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub struct Foo;
1214

1315
impl Foo {

src/test/auxiliary/issue-22025.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub mod foo {
1214

1315
pub trait Foo {}

src/test/auxiliary/issue-27362.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
#![feature(const_fn)]
1214

1315
pub const fn foo() {}

src/test/auxiliary/issue-29584.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// compile-flags: -Cmetadata=aux
12+
1113
pub struct Foo;
1214

1315
#[doc(hidden)]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-include ../tools.mk
22

33
all:
4-
$(RUSTC) libc.rs
4+
$(RUSTC) libc.rs -Cmetadata=foo
55
$(RUSTC) main.rs --extern libc=$(TMPDIR)/liblibc.rlib

src/test/run-make/issue-26006/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ time: libc
1212

1313
libc:
1414
mkdir -p $(OUT)/libc
15-
$(RUSTC) in/libc/lib.rs --crate-name=libc -o $(OUT)/libc/liblibc.rlib
15+
$(RUSTC) in/libc/lib.rs --crate-name=libc -Cmetadata=foo -o $(OUT)/libc/liblibc.rlib
1616
else
1717
all:
1818
endif

0 commit comments

Comments
 (0)