rustc: Fix a leak in dependency= paths
With the addition of separate search paths to the compiler, it was intended that
applications such as Cargo could require a `--extern` flag per `extern crate`
directive in the source. The system can currently be subverted, however, due to
the `existing_match()` logic in the crate loader.
When loading crates we first attempt to match an `extern crate` directive
against all previously loaded crates to avoid reading metadata twice. This "hit
the cache if possible" step was erroneously leaking crates across the search
path boundaries, however. For example:
extern crate b;
extern crate a;
If `b` depends on `a`, then it will load crate `a` when the `extern crate b`
directive is being processed. When the compiler reaches `extern crate a` it will
use the previously loaded version no matter what. If the compiler was not
invoked with `-L crate=path/to/a`, it will still succeed.
This behavior is allowing `extern crate` declarations in Cargo without a
corresponding declaration in the manifest of a dependency, which is considered
a bug.
This commit fixes this problem by keeping track of the origin search path for a
crate. Crates loaded from the dependency search path are not candidates for
crates which are loaded from the crate search path.
As a result of this fix, this is a likely a breaking change for a number of
Cargo packages. If the compiler starts informing that a crate can no longer be
found, it likely means that the dependency was forgotten in your Cargo.toml.
[breaking-change]
This commit is contained in:
parent
6ba9acd8ab
commit
cbeb77ec7a
15 changed files with 145 additions and 78 deletions
8
src/test/run-make/compiler-lookup-paths-2/Makefile
Normal file
8
src/test/run-make/compiler-lookup-paths-2/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
mkdir -p $(TMPDIR)/a $(TMPDIR)/b
|
||||
$(RUSTC) a.rs && mv $(TMPDIR)/liba.rlib $(TMPDIR)/a
|
||||
$(RUSTC) b.rs -L $(TMPDIR)/a && mv $(TMPDIR)/libb.rlib $(TMPDIR)/b
|
||||
$(RUSTC) c.rs -L crate=$(TMPDIR)/b -L dependency=$(TMPDIR)/a \
|
||||
&& exit 1 || exit 0
|
||||
11
src/test/run-make/compiler-lookup-paths-2/a.rs
Normal file
11
src/test/run-make/compiler-lookup-paths-2/a.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 = "lib"]
|
||||
12
src/test/run-make/compiler-lookup-paths-2/b.rs
Normal file
12
src/test/run-make/compiler-lookup-paths-2/b.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// 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 = "lib"]
|
||||
extern crate a;
|
||||
13
src/test/run-make/compiler-lookup-paths-2/c.rs
Normal file
13
src/test/run-make/compiler-lookup-paths-2/c.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// 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 = "lib"]
|
||||
extern crate b;
|
||||
extern crate a;
|
||||
|
|
@ -17,8 +17,10 @@ all:
|
|||
$(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs
|
||||
$(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib
|
||||
$(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib
|
||||
@echo before
|
||||
$(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib
|
||||
$(call RUN,d)
|
||||
@echo after
|
||||
$(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib
|
||||
$(call RUN,d)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@
|
|||
#![crate_name = "a"]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
static FOO: uint = 3;
|
||||
static FOO: usize = 3;
|
||||
|
||||
pub fn token() -> &'static uint { &FOO }
|
||||
pub fn token() -> &'static usize { &FOO }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
extern crate a;
|
||||
|
||||
static FOO: uint = 3;
|
||||
static FOO: usize = 3;
|
||||
|
||||
pub fn token() -> &'static uint { &FOO }
|
||||
pub fn a_token() -> &'static uint { a::token() }
|
||||
pub fn token() -> &'static usize { &FOO }
|
||||
pub fn a_token() -> &'static usize { a::token() }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
extern crate a;
|
||||
|
||||
static FOO: uint = 3;
|
||||
static FOO: usize = 3;
|
||||
|
||||
pub fn token() -> &'static uint { &FOO }
|
||||
pub fn a_token() -> &'static uint { a::token() }
|
||||
pub fn token() -> &'static usize { &FOO }
|
||||
pub fn a_token() -> &'static usize { a::token() }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ extern crate b;
|
|||
extern crate c;
|
||||
#[cfg(after)] extern crate a;
|
||||
|
||||
fn t(a: &'static uint) -> uint { a as *const _ as uint }
|
||||
fn t(a: &'static usize) -> usize { a as *const _ as usize }
|
||||
|
||||
fn main() {
|
||||
assert!(t(a::token()) == t(b::a_token()));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue