From 37bf97a0f9cc764a19dfcff21d62384b2445dcbc Mon Sep 17 00:00:00 2001
From: gentlefolk <cemacken@gmail.com>
Date: Sun, 9 Feb 2014 22:29:21 -0500
Subject: [PATCH] Updated metadata::creader::resolve_crate_deps to use the
 correct span. Clarified error message when an external crate's dependency is
 missing. Closes #2404.

---
 src/librustc/metadata/creader.rs              | 29 ++++++++++++++-----
 src/librustc/metadata/loader.rs               | 12 +++++---
 .../missing-crate-dependency/Makefile         |  9 ++++++
 .../missing-crate-dependency/crateA.rs        | 12 ++++++++
 .../missing-crate-dependency/crateB.rs        | 11 +++++++
 .../missing-crate-dependency/crateC.rs        | 13 +++++++++
 6 files changed, 74 insertions(+), 12 deletions(-)
 create mode 100644 src/test/run-make/missing-crate-dependency/Makefile
 create mode 100644 src/test/run-make/missing-crate-dependency/crateA.rs
 create mode 100644 src/test/run-make/missing-crate-dependency/crateB.rs
 create mode 100644 src/test/run-make/missing-crate-dependency/crateC.rs

diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 901e8982c83..df250937a57 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -24,7 +24,7 @@ use syntax::ast;
 use syntax::abi;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
-use syntax::codemap::{Span, DUMMY_SP};
+use syntax::codemap::{Span};
 use syntax::diagnostic::SpanHandler;
 use syntax::ext::base::{CrateLoader, MacroCrate};
 use syntax::parse::token::{IdentInterner, InternedString};
@@ -147,6 +147,7 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
     match extract_crate_info(i) {
         Some(info) => {
             let cnum = resolve_crate(e,
+                                     None,
                                      info.ident.clone(),
                                      info.name.clone(),
                                      info.version.clone(),
@@ -299,6 +300,7 @@ fn existing_match(e: &Env, name: &str, version: &str, hash: &str) -> Option<ast:
 }
 
 fn resolve_crate(e: &mut Env,
+                 root_ident: Option<~str>,
                  ident: ~str,
                  name: ~str,
                  version: ~str,
@@ -319,7 +321,7 @@ fn resolve_crate(e: &mut Env,
         };
         let loader::Library {
             dylib, rlib, metadata
-        } = load_ctxt.load_library_crate();
+        } = load_ctxt.load_library_crate(root_ident.clone());
 
         let attrs = decoder::get_crate_attributes(metadata.as_slice());
         let crateid = attr::find_crateid(attrs).unwrap();
@@ -338,8 +340,17 @@ fn resolve_crate(e: &mut Env,
         }
         e.next_crate_num += 1;
 
+        // Maintain a reference to the top most crate.
+        let root_crate = match root_ident {
+            Some(c) => c,
+            None => load_ctxt.ident.clone()
+        };
+
         // Now resolve the crates referenced by this crate
-        let cnum_map = resolve_crate_deps(e, metadata.as_slice());
+        let cnum_map = resolve_crate_deps(e,
+                                          Some(root_crate),
+                                          metadata.as_slice(),
+                                          span);
 
         let cmeta = @cstore::crate_metadata {
             name: load_ctxt.name,
@@ -364,7 +375,10 @@ fn resolve_crate(e: &mut Env,
 }
 
 // Go through the crate metadata and load any crates that it references
-fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map {
+fn resolve_crate_deps(e: &mut Env,
+                      root_ident: Option<~str>,
+                      cdata: &[u8], span : Span)
+                   -> cstore::cnum_map {
     debug!("resolving deps of external crate");
     // The map from crate numbers in the crate we're resolving to local crate
     // numbers
@@ -387,15 +401,13 @@ fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map {
           None => {
             debug!("need to load it");
             // This is a new one so we've got to load it
-            // FIXME (#2404): Need better error reporting than just a bogus
-            // span.
-            let fake_span = DUMMY_SP;
             let local_cnum = resolve_crate(e,
+                                           root_ident.clone(),
                                            cname_str.get().to_str(),
                                            cname_str.get().to_str(),
                                            dep.vers.clone(),
                                            dep.hash.clone(),
-                                           fake_span);
+                                           span);
             cnum_map.insert(extrn_cnum, local_cnum);
           }
         }
@@ -427,6 +439,7 @@ impl CrateLoader for Loader {
     fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
         let info = extract_crate_info(krate).unwrap();
         let cnum = resolve_crate(&mut self.env,
+                                 None,
                                  info.ident.clone(),
                                  info.name.clone(),
                                  info.version.clone(),
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 8a7964fcf6b..5539347949a 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -65,13 +65,17 @@ pub struct ArchiveMetadata {
 }
 
 impl Context {
-    pub fn load_library_crate(&self) -> Library {
+    pub fn load_library_crate(&self, root_ident: Option<~str>) -> Library {
         match self.find_library_crate() {
             Some(t) => t,
             None => {
-                self.sess.span_fatal(self.span,
-                                     format!("can't find crate for `{}`",
-                                             self.ident));
+                let message = match root_ident {
+                    None => format!("can't find crate for `{}`", self.ident),
+                    Some(c) => format!("can't find crate for `{}` which `{}` depends on",
+                                       self.ident,
+                                       c)
+                };
+                self.sess.span_fatal(self.span, message);
             }
         }
     }
diff --git a/src/test/run-make/missing-crate-dependency/Makefile b/src/test/run-make/missing-crate-dependency/Makefile
new file mode 100644
index 00000000000..a470ee0a7c1
--- /dev/null
+++ b/src/test/run-make/missing-crate-dependency/Makefile
@@ -0,0 +1,9 @@
+-include ../tools.mk
+
+all: 
+	$(RUSTC) --crate-type=rlib crateA.rs
+	$(RUSTC) --crate-type=rlib crateB.rs
+	rm $(TMPDIR)/$(call RLIB_GLOB,crateA)
+	# Ensure crateC fails to compile since dependency crateA is missing
+	$(RUSTC) crateC.rs 2>&1 | \
+		grep "error: can't find crate for \`crateA\` which \`crateB\` depends on"
diff --git a/src/test/run-make/missing-crate-dependency/crateA.rs b/src/test/run-make/missing-crate-dependency/crateA.rs
new file mode 100644
index 00000000000..4e111f29e8a
--- /dev/null
+++ b/src/test/run-make/missing-crate-dependency/crateA.rs
@@ -0,0 +1,12 @@
+// Copyright 2014 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.
+
+// Base crate
+pub fn func() {}
diff --git a/src/test/run-make/missing-crate-dependency/crateB.rs b/src/test/run-make/missing-crate-dependency/crateB.rs
new file mode 100644
index 00000000000..bf55017c646
--- /dev/null
+++ b/src/test/run-make/missing-crate-dependency/crateB.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 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 crateA;
diff --git a/src/test/run-make/missing-crate-dependency/crateC.rs b/src/test/run-make/missing-crate-dependency/crateC.rs
new file mode 100644
index 00000000000..174d9382b76
--- /dev/null
+++ b/src/test/run-make/missing-crate-dependency/crateC.rs
@@ -0,0 +1,13 @@
+// Copyright 2014 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 crateB;
+
+fn main() {}