mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03: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:
@@ -368,7 +368,12 @@ fn resolve_crate(&mut self,
|
||||
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 @@ fn resolve_crate(&mut self,
|
||||
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 @@ fn extract_one(&mut self, m: HashMap<PathBuf, PathKind>, flavor: &str,
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
@@ -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() {
|
||||
/* ... */
|
||||
}
|
||||
@@ -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"]
|
||||
@@ -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"]
|
||||
Reference in New Issue
Block a user