提交 731c0ce4 编写于 作者: B bors

Auto merge of #29961 - alexcrichton:order-dependent, r=brson

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.
......@@ -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);
......
-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
// 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() {
/* ... */
}
// 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"]
// 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"]
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册