mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 18:23:49 +00:00
rustc: Fix extern crate
being order dependent
This commit fixes a bug where a crate could fail to compile depending on the order of `extern crate` directives at the top of the crate. Specifically, if the same crate is found at two locations, then if it's loaded first via `--extern` it will not emit a duplicate warning, but if it's first loaded transitively via a dep and *then* via `--extern` an error will be emitted. The loader was tweaked to catch this scenario and coalesce the loading of these two crates to prevent errors from being emitted.
This commit is contained in:
parent
1902021032
commit
24311d0762
@ -368,7 +368,12 @@ impl<'a> CrateReader<'a> {
|
||||
explicitly_linked: bool)
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||
cstore::CrateSource) {
|
||||
match self.existing_match(name, hash, kind) {
|
||||
enum LookupResult {
|
||||
Previous(ast::CrateNum),
|
||||
Loaded(loader::Library),
|
||||
}
|
||||
let result = match self.existing_match(name, hash, kind) {
|
||||
Some(cnum) => LookupResult::Previous(cnum),
|
||||
None => {
|
||||
let mut load_ctxt = loader::Context {
|
||||
sess: self.sess,
|
||||
@ -386,16 +391,36 @@ impl<'a> CrateReader<'a> {
|
||||
should_match_name: true,
|
||||
};
|
||||
let library = load_ctxt.load_library_crate();
|
||||
self.register_crate(root, ident, name, span, library,
|
||||
explicitly_linked)
|
||||
|
||||
// In the case that we're loading a crate, but not matching
|
||||
// against a hash, we could load a crate which has the same hash
|
||||
// as an already loaded crate. If this is the case prevent
|
||||
// duplicates by just using the first crate.
|
||||
let meta_hash = decoder::get_crate_hash(library.metadata
|
||||
.as_slice());
|
||||
let mut result = LookupResult::Loaded(library);
|
||||
self.sess.cstore.iter_crate_data(|cnum, data| {
|
||||
if data.name() == name && meta_hash == data.hash() {
|
||||
assert!(hash.is_none());
|
||||
result = LookupResult::Previous(cnum);
|
||||
}
|
||||
});
|
||||
result
|
||||
}
|
||||
Some(cnum) => {
|
||||
};
|
||||
|
||||
match result {
|
||||
LookupResult::Previous(cnum) => {
|
||||
let data = self.sess.cstore.get_crate_data(cnum);
|
||||
if explicitly_linked && !data.explicitly_linked.get() {
|
||||
data.explicitly_linked.set(explicitly_linked);
|
||||
}
|
||||
(cnum, data, self.sess.cstore.get_used_crate_source(cnum).unwrap())
|
||||
}
|
||||
LookupResult::Loaded(library) => {
|
||||
self.register_crate(root, ident, name, span, library,
|
||||
explicitly_linked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,7 +547,12 @@ impl<'a> Context<'a> {
|
||||
continue
|
||||
}
|
||||
};
|
||||
if ret.is_some() {
|
||||
// If we've already found a candidate and we're not matching hashes,
|
||||
// emit an error about duplicate candidates found. If we're matching
|
||||
// based on a hash, however, then if we've gotten this far both
|
||||
// candidates have the same hash, so they're not actually
|
||||
// duplicates that we should warn about.
|
||||
if ret.is_some() && self.hash.is_none() {
|
||||
span_err!(self.sess, self.span, E0465,
|
||||
"multiple {} candidates for `{}` found",
|
||||
flavor, self.crate_name);
|
||||
|
8
src/test/run-make/extern-multiple-copies/Makefile
Normal file
8
src/test/run-make/extern-multiple-copies/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) foo1.rs
|
||||
$(RUSTC) foo2.rs
|
||||
mkdir $(TMPDIR)/foo
|
||||
cp $(TMPDIR)/libfoo1.rlib $(TMPDIR)/foo/libfoo1.rlib
|
||||
$(RUSTC) bar.rs --extern foo1=$(TMPDIR)/libfoo1.rlib -L $(TMPDIR)/foo
|
16
src/test/run-make/extern-multiple-copies/bar.rs
Normal file
16
src/test/run-make/extern-multiple-copies/bar.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate foo2; // foo2 first to exhibit the bug
|
||||
extern crate foo1;
|
||||
|
||||
fn main() {
|
||||
/* ... */
|
||||
}
|
11
src/test/run-make/extern-multiple-copies/foo1.rs
Normal file
11
src/test/run-make/extern-multiple-copies/foo1.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "rlib"]
|
11
src/test/run-make/extern-multiple-copies/foo2.rs
Normal file
11
src/test/run-make/extern-multiple-copies/foo2.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_type = "rlib"]
|
Loading…
Reference in New Issue
Block a user