Check metadata hash when loading transitive dependent crates
Fix issue #2138
This commit is contained in:
parent
18597b22b5
commit
7d227f21f7
3 changed files with 58 additions and 24 deletions
|
@ -34,6 +34,7 @@ fn read_crates(sess: session::session, crate: ast::crate) {
|
||||||
type cache_entry = {
|
type cache_entry = {
|
||||||
cnum: int,
|
cnum: int,
|
||||||
span: span,
|
span: span,
|
||||||
|
hash: str,
|
||||||
metas: @[@ast::meta_item]
|
metas: @[@ast::meta_item]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ type env = @{sess: session::session,
|
||||||
fn visit_view_item(e: env, i: @ast::view_item) {
|
fn visit_view_item(e: env, i: @ast::view_item) {
|
||||||
alt i.node {
|
alt i.node {
|
||||||
ast::view_item_use(ident, meta_items, id) {
|
ast::view_item_use(ident, meta_items, id) {
|
||||||
let cnum = resolve_crate(e, ident, meta_items, i.span);
|
let cnum = resolve_crate(e, ident, meta_items, "", i.span);
|
||||||
cstore::add_use_stmt_cnum(e.sess.cstore, id, cnum);
|
cstore::add_use_stmt_cnum(e.sess.cstore, id, cnum);
|
||||||
}
|
}
|
||||||
_ { }
|
_ { }
|
||||||
|
@ -140,9 +141,14 @@ fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item]) -> bool {
|
fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
|
||||||
|
bool {
|
||||||
let attrs = decoder::get_crate_attributes(crate_data);
|
let attrs = decoder::get_crate_attributes(crate_data);
|
||||||
let linkage_metas = attr::find_linkage_metas(attrs);
|
let linkage_metas = attr::find_linkage_metas(attrs);
|
||||||
|
if hash.is_not_empty() {
|
||||||
|
let chash = decoder::get_crate_hash(crate_data);
|
||||||
|
if chash != hash { ret false; }
|
||||||
|
}
|
||||||
metadata_matches(linkage_metas, metas)
|
metadata_matches(linkage_metas, metas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,30 +200,30 @@ fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_library_crate(sess: session::session, span: span,
|
fn find_library_crate(sess: session::session, span: span,
|
||||||
metas: [@ast::meta_item])
|
metas: [@ast::meta_item], hash: str)
|
||||||
-> option<{ident: str, data: @[u8]}> {
|
-> option<{ident: str, data: @[u8]}> {
|
||||||
|
|
||||||
attr::require_unique_names(sess.diagnostic(), metas);
|
attr::require_unique_names(sess.diagnostic(), metas);
|
||||||
let metas = metas;
|
let metas = metas;
|
||||||
let crate_name = crate_name_from_metas(metas);
|
|
||||||
|
|
||||||
let nn = default_native_lib_naming(sess, sess.opts.static);
|
let nn = default_native_lib_naming(sess, sess.opts.static);
|
||||||
let x =
|
let x =
|
||||||
find_library_crate_aux(sess, span, nn, crate_name,
|
find_library_crate_aux(sess, span, nn,
|
||||||
metas, sess.filesearch);
|
metas, hash, sess.filesearch);
|
||||||
if x != none || sess.opts.static { ret x; }
|
if x != none || sess.opts.static { ret x; }
|
||||||
let nn2 = default_native_lib_naming(sess, true);
|
let nn2 = default_native_lib_naming(sess, true);
|
||||||
ret find_library_crate_aux(sess, span, nn2, crate_name, metas,
|
ret find_library_crate_aux(sess, span, nn2, metas, hash,
|
||||||
sess.filesearch);
|
sess.filesearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_library_crate_aux(sess: session::session,
|
fn find_library_crate_aux(sess: session::session,
|
||||||
span: span,
|
span: span,
|
||||||
nn: {prefix: str, suffix: str},
|
nn: {prefix: str, suffix: str},
|
||||||
crate_name: str,
|
|
||||||
metas: [@ast::meta_item],
|
metas: [@ast::meta_item],
|
||||||
|
hash: str,
|
||||||
filesearch: filesearch::filesearch) ->
|
filesearch: filesearch::filesearch) ->
|
||||||
option<{ident: str, data: @[u8]}> {
|
option<{ident: str, data: @[u8]}> {
|
||||||
|
let crate_name = crate_name_from_metas(metas);
|
||||||
let prefix: str = nn.prefix + crate_name + "-";
|
let prefix: str = nn.prefix + crate_name + "-";
|
||||||
let suffix: str = nn.suffix;
|
let suffix: str = nn.suffix;
|
||||||
|
|
||||||
|
@ -233,7 +239,7 @@ fn find_library_crate_aux(sess: session::session,
|
||||||
#debug("%s is a candidate", path);
|
#debug("%s is a candidate", path);
|
||||||
alt get_metadata_section(sess, path) {
|
alt get_metadata_section(sess, path) {
|
||||||
option::some(cvec) {
|
option::some(cvec) {
|
||||||
if !crate_matches(cvec, metas) {
|
if !crate_matches(cvec, metas, hash) {
|
||||||
#debug("skipping %s, metadata doesn't match", path);
|
#debug("skipping %s, metadata doesn't match", path);
|
||||||
option::none
|
option::none
|
||||||
} else {
|
} else {
|
||||||
|
@ -302,11 +308,11 @@ fn get_metadata_section(sess: session::session,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
|
fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
|
||||||
metas: [@ast::meta_item])
|
metas: [@ast::meta_item], hash: str)
|
||||||
-> {ident: str, data: @[u8]} {
|
-> {ident: str, data: @[u8]} {
|
||||||
|
|
||||||
|
|
||||||
alt find_library_crate(sess, span, metas) {
|
alt find_library_crate(sess, span, metas, hash) {
|
||||||
some(t) { ret t; }
|
some(t) { ret t; }
|
||||||
none {
|
none {
|
||||||
sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
|
sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
|
||||||
|
@ -329,32 +335,36 @@ fn metas_with_ident(ident: ast::ident,
|
||||||
metas_with(ident, "name", metas)
|
metas_with(ident, "name", metas)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn existing_match(e: env, metas: [@ast::meta_item]) -> option<int> {
|
fn existing_match(e: env, metas: [@ast::meta_item], hash: str) ->
|
||||||
|
option<int> {
|
||||||
let maybe_entry = e.crate_cache.find {|c|
|
let maybe_entry = e.crate_cache.find {|c|
|
||||||
metadata_matches(*c.metas, metas)
|
metadata_matches(*c.metas, metas) &&
|
||||||
|
(hash.is_empty() || c.hash == hash)
|
||||||
};
|
};
|
||||||
|
|
||||||
maybe_entry.map {|c| c.cnum }
|
maybe_entry.map {|c| c.cnum }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
|
fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
|
||||||
span: span) -> ast::crate_num {
|
hash: str, span: span) -> ast::crate_num {
|
||||||
let metas = metas_with_ident(ident, metas);
|
let metas = metas_with_ident(ident, metas);
|
||||||
|
|
||||||
alt existing_match(e, metas) {
|
alt existing_match(e, metas, hash) {
|
||||||
none {
|
none {
|
||||||
let cinfo =
|
let cinfo =
|
||||||
load_library_crate(e.sess, ident, span, metas);
|
load_library_crate(e.sess, ident, span, metas, hash);
|
||||||
|
|
||||||
let cfilename = cinfo.ident;
|
let cfilename = cinfo.ident;
|
||||||
let cdata = cinfo.data;
|
let cdata = cinfo.data;
|
||||||
|
|
||||||
let attrs = decoder::get_crate_attributes(cdata);
|
let attrs = decoder::get_crate_attributes(cdata);
|
||||||
let linkage_metas = attr::find_linkage_metas(attrs);
|
let linkage_metas = attr::find_linkage_metas(attrs);
|
||||||
|
let hash = decoder::get_crate_hash(cdata);
|
||||||
|
|
||||||
// Claim this crate number and cache it
|
// Claim this crate number and cache it
|
||||||
let cnum = e.next_crate_num;
|
let cnum = e.next_crate_num;
|
||||||
e.crate_cache += [{cnum: cnum, span: span, metas: @linkage_metas}];
|
e.crate_cache += [{cnum: cnum, span: span,
|
||||||
|
hash: hash, metas: @linkage_metas}];
|
||||||
e.next_crate_num += 1;
|
e.next_crate_num += 1;
|
||||||
|
|
||||||
// Now resolve the crates referenced by this crate
|
// Now resolve the crates referenced by this crate
|
||||||
|
@ -387,12 +397,10 @@ fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
|
||||||
for decoder::get_crate_deps(cdata).each {|dep|
|
for decoder::get_crate_deps(cdata).each {|dep|
|
||||||
let extrn_cnum = dep.cnum;
|
let extrn_cnum = dep.cnum;
|
||||||
let cname = dep.name;
|
let cname = dep.name;
|
||||||
let cvers = dep.vers;
|
let cmetas = metas_with(dep.vers, "vers", []);
|
||||||
// FIXME: We really need to know the linkage metas of our transitive
|
#debug("resolving dep crate %s ver: %s hash: %s",
|
||||||
// dependencies in order to resolve them correctly.
|
dep.name, dep.vers, dep.hash);
|
||||||
let cmetas = metas_with(cvers, "vers", []);
|
alt existing_match(e, metas_with_ident(cname, cmetas), dep.hash) {
|
||||||
#debug("resolving dep %s ver: %s", cname, dep.vers);
|
|
||||||
alt existing_match(e, metas_with_ident(cname, cmetas)) {
|
|
||||||
some(local_cnum) {
|
some(local_cnum) {
|
||||||
#debug("already have it");
|
#debug("already have it");
|
||||||
// We've already seen this crate
|
// We've already seen this crate
|
||||||
|
@ -403,7 +411,8 @@ fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
|
||||||
// This is a new one so we've got to load it
|
// This is a new one so we've got to load it
|
||||||
// FIXME: Need better error reporting than just a bogus span
|
// FIXME: Need better error reporting than just a bogus span
|
||||||
let fake_span = ast_util::dummy_sp();
|
let fake_span = ast_util::dummy_sp();
|
||||||
let local_cnum = resolve_crate(e, cname, cmetas, fake_span);
|
let local_cnum =
|
||||||
|
resolve_crate(e, cname, cmetas, dep.hash, fake_span);
|
||||||
cnum_map.insert(extrn_cnum, local_cnum);
|
cnum_map.insert(extrn_cnum, local_cnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/test/auxiliary/crateresolve7x.rs
Normal file
14
src/test/auxiliary/crateresolve7x.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// xfail-fast
|
||||||
|
// aux-build:crateresolve6-1.rs
|
||||||
|
// aux-build:crateresolve6-2.rs
|
||||||
|
|
||||||
|
// These both have the same version but differ in other metadata
|
||||||
|
mod a {
|
||||||
|
use cr6_1 (name = "crateresolve6", vers = "0.1", calories="100");
|
||||||
|
fn f() -> int { cr6_1::f() }
|
||||||
|
}
|
||||||
|
|
||||||
|
mod b {
|
||||||
|
use cr6_2 (name = "crateresolve6", vers = "0.1", calories="200");
|
||||||
|
fn f() -> int { cr6_2::f() }
|
||||||
|
}
|
11
src/test/run-pass/crateresolve7.rs
Normal file
11
src/test/run-pass/crateresolve7.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// xfail-fast
|
||||||
|
// aux-build:crateresolve6-1.rs
|
||||||
|
// aux-build:crateresolve6-2.rs
|
||||||
|
// aux-build:crateresolve7x.rs
|
||||||
|
|
||||||
|
use crateresolve7x;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert crateresolve7x::a::f() == 100;
|
||||||
|
assert crateresolve7x::b::f() == 200;
|
||||||
|
}
|
Loading…
Reference in a new issue