Skip to content

Commit 3ccbffa

Browse files
committed
After a hash mismatch error, emit file-system paths of crates involved.
Fix #13266. There is a little bit of acrobatics in the definition of `crate_paths` to avoid calling `clone()` on the dylib/rlib unless we actually are going to need them. The other oddity is that I have replaced the `root_ident: Option<&str>` parameter with a `root: &Option<CratePaths>`, which may surprise one who was expecting to see something like: `root: Option<&CratePaths>`. I went with the approach here because I could not come up with code for the alternative that was acceptable to the borrow checker.
1 parent 7bda3df commit 3ccbffa

File tree

2 files changed

+70
-28
lines changed

2 files changed

+70
-28
lines changed

src/librustc/metadata/creader.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use metadata::cstore;
2121
use metadata::decoder;
2222
use metadata::loader;
2323
use metadata::loader::Os;
24+
use metadata::loader::CratePaths;
2425

2526
use std::cell::RefCell;
2627
use std::rc::Rc;
@@ -141,7 +142,7 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
141142

142143
match extract_crate_info(e, i) {
143144
Some(info) => {
144-
let cnum = resolve_crate(e, None, info.ident, &info.crate_id, None,
145+
let cnum = resolve_crate(e, &None, info.ident, &info.crate_id, None,
145146
i.span);
146147
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
147148
}
@@ -278,13 +279,13 @@ fn existing_match(e: &Env, crate_id: &CrateId,
278279
None
279280
}
280281

281-
fn resolve_crate(e: &mut Env,
282-
root_ident: Option<&str>,
283-
ident: &str,
284-
crate_id: &CrateId,
285-
hash: Option<&Svh>,
286-
span: Span)
287-
-> ast::CrateNum {
282+
fn resolve_crate<'a>(e: &mut Env,
283+
root: &Option<CratePaths>,
284+
ident: &str,
285+
crate_id: &CrateId,
286+
hash: Option<&Svh>,
287+
span: Span)
288+
-> ast::CrateNum {
288289
match existing_match(e, crate_id, hash) {
289290
None => {
290291
let id_hash = link::crate_id_hash(crate_id);
@@ -297,11 +298,11 @@ fn resolve_crate(e: &mut Env,
297298
hash: hash.map(|a| &*a),
298299
os: e.os,
299300
intr: e.intr.clone(),
300-
rejected_via_hash: false,
301+
rejected_via_hash: None,
301302
};
302303
let loader::Library {
303304
dylib, rlib, metadata
304-
} = load_ctxt.load_library_crate(root_ident);
305+
} = load_ctxt.load_library_crate(root);
305306

306307
let crate_id = decoder::get_crate_id(metadata.as_slice());
307308
let hash = decoder::get_crate_hash(metadata.as_slice());
@@ -316,15 +317,22 @@ fn resolve_crate(e: &mut Env,
316317
});
317318
e.next_crate_num += 1;
318319

319-
// Maintain a reference to the top most crate.
320-
let root_crate = match root_ident {
321-
Some(c) => c,
322-
None => load_ctxt.ident.clone()
320+
// Stash paths for top-most crate locally if necessary.
321+
let crate_paths = if root.is_none() {
322+
Some(CratePaths {
323+
ident: load_ctxt.ident.to_owned(),
324+
dylib: dylib.clone(),
325+
rlib: rlib.clone(),
326+
})
327+
} else {
328+
None
323329
};
330+
// Maintain a reference to the top most crate.
331+
let root = if root.is_some() { root } else { &crate_paths };
324332

325333
// Now resolve the crates referenced by this crate
326334
let cnum_map = resolve_crate_deps(e,
327-
Some(root_crate),
335+
root,
328336
metadata.as_slice(),
329337
span);
330338

@@ -349,7 +357,7 @@ fn resolve_crate(e: &mut Env,
349357

350358
// Go through the crate metadata and load any crates that it references
351359
fn resolve_crate_deps(e: &mut Env,
352-
root_ident: Option<&str>,
360+
root: &Option<CratePaths>,
353361
cdata: &[u8], span : Span)
354362
-> cstore::cnum_map {
355363
debug!("resolving deps of external crate");
@@ -360,7 +368,7 @@ fn resolve_crate_deps(e: &mut Env,
360368
for dep in r.iter() {
361369
let extrn_cnum = dep.cnum;
362370
debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
363-
let local_cnum = resolve_crate(e, root_ident,
371+
let local_cnum = resolve_crate(e, root,
364372
dep.crate_id.name.as_slice(),
365373
&dep.crate_id,
366374
Some(&dep.hash),
@@ -393,7 +401,7 @@ impl<'a> Loader<'a> {
393401
impl<'a> CrateLoader for Loader<'a> {
394402
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
395403
let info = extract_crate_info(&self.env, krate).unwrap();
396-
let cnum = resolve_crate(&mut self.env, None, info.ident,
404+
let cnum = resolve_crate(&mut self.env, &None, info.ident,
397405
&info.crate_id, None, krate.span);
398406
let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
399407
MacroCrate {

src/librustc/metadata/loader.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ pub enum Os {
4545
OsFreebsd
4646
}
4747

48+
pub struct ViaHash {
49+
path: Path,
50+
}
51+
4852
pub struct Context<'a> {
4953
pub sess: &'a Session,
5054
pub span: Span,
@@ -54,7 +58,8 @@ pub struct Context<'a> {
5458
pub hash: Option<&'a Svh>,
5559
pub os: Os,
5660
pub intr: Rc<IdentInterner>,
57-
pub rejected_via_hash: bool,
61+
/// Some if rejected
62+
pub rejected_via_hash: Option<ViaHash>
5863
}
5964

6065
pub struct Library {
@@ -69,6 +74,25 @@ pub struct ArchiveMetadata {
6974
data: &'static [u8],
7075
}
7176

77+
pub struct CratePaths {
78+
pub ident: ~str,
79+
pub dylib: Option<Path>,
80+
pub rlib: Option<Path>
81+
}
82+
83+
impl CratePaths {
84+
fn describe_paths(&self) -> ~str {
85+
match (&self.dylib, &self.rlib) {
86+
(&None, &None)
87+
=> ~"",
88+
(&Some(ref p), &None) | (&None, &Some(ref p))
89+
=> format!("{}", p.display()),
90+
(&Some(ref p1), &Some(ref p2))
91+
=> format!("{}, {}", p1.display(), p2.display()),
92+
}
93+
}
94+
}
95+
7296
// FIXME(#11857) this should be a "real" realpath
7397
fn realpath(p: &Path) -> Path {
7498
use std::os;
@@ -82,26 +106,35 @@ fn realpath(p: &Path) -> Path {
82106
}
83107

84108
impl<'a> Context<'a> {
85-
pub fn load_library_crate(&mut self, root_ident: Option<&str>) -> Library {
109+
pub fn load_library_crate(&mut self, root: &Option<CratePaths>) -> Library {
86110
match self.find_library_crate() {
87111
Some(t) => t,
88112
None => {
89113
self.sess.abort_if_errors();
90-
let message = if self.rejected_via_hash {
114+
let message = if self.rejected_via_hash.is_some() {
91115
format!("found possibly newer version of crate `{}`",
92116
self.ident)
93117
} else {
94118
format!("can't find crate for `{}`", self.ident)
95119
};
96-
let message = match root_ident {
97-
None => message,
98-
Some(c) => format!("{} which `{}` depends on", message, c),
120+
let message = match root {
121+
&None => message,
122+
&Some(ref r) => format!("{} which `{}` depends on",
123+
message, r.ident)
99124
};
100125
self.sess.span_err(self.span, message);
101126

102-
if self.rejected_via_hash {
127+
if self.rejected_via_hash.is_some() {
103128
self.sess.span_note(self.span, "perhaps this crate needs \
104129
to be recompiled?");
130+
self.rejected_via_hash.as_ref().map(
131+
|r| self.sess.note(format!(
132+
"crate `{}` at path: {}",
133+
self.ident, r.path.display())));
134+
root.as_ref().map(
135+
|r| self.sess.note(format!(
136+
"crate `{}` at path(s): {}",
137+
r.ident, r.describe_paths())));
105138
}
106139
self.sess.abort_if_errors();
107140
unreachable!()
@@ -291,7 +324,7 @@ impl<'a> Context<'a> {
291324
info!("{} reading metadata from: {}", flavor, lib.display());
292325
let metadata = match get_metadata_section(self.os, &lib) {
293326
Ok(blob) => {
294-
if self.crate_matches(blob.as_slice()) {
327+
if self.crate_matches(blob.as_slice(), &lib) {
295328
blob
296329
} else {
297330
info!("metadata mismatch");
@@ -326,7 +359,7 @@ impl<'a> Context<'a> {
326359
return if error > 0 {None} else {ret}
327360
}
328361

329-
fn crate_matches(&mut self, crate_data: &[u8]) -> bool {
362+
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
330363
match decoder::maybe_get_crate_id(crate_data) {
331364
Some(ref id) if self.crate_id.matches(id) => {}
332365
_ => return false
@@ -338,7 +371,8 @@ impl<'a> Context<'a> {
338371
None => true,
339372
Some(myhash) => {
340373
if *myhash != hash {
341-
self.rejected_via_hash = true;
374+
self.rejected_via_hash =
375+
Some(ViaHash{ path: libpath.clone(), });
342376
false
343377
} else {
344378
true

0 commit comments

Comments
 (0)