about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-09 16:17:10 -0700
committerbors <bors@rust-lang.org>2013-08-09 16:17:10 -0700
commit6f6dce7bbcfb104a8a1e23b0b93d83cbb770f338 (patch)
tree1f5f151dfd5c72f41338c495a38b422ea4aa552c /src/librustc
parent1de201c3c6ee1e563ca58d4d6b288929e841081e (diff)
parent37fd8f03fdbc622457396877168d2a8d82cf3d2b (diff)
auto merge of #8176 : catamorphism/rust/rustpkg-extern-mod, r=catamorphism
r? @graydon Also, notably, make rustpkgtest depend on the rustpkg executable (otherwise, tests that shell out to rustpgk might run when rustpkg doesn't exist).
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/back/link.rs23
-rw-r--r--src/librustc/back/rpath.rs117
-rw-r--r--src/librustc/front/std_inject.rs2
-rw-r--r--src/librustc/front/test.rs2
-rw-r--r--src/librustc/metadata/common.rs2
-rw-r--r--src/librustc/metadata/creader.rs45
-rw-r--r--src/librustc/metadata/filesearch.rs143
-rw-r--r--src/librustc/metadata/loader.rs78
-rw-r--r--src/librustc/middle/resolve.rs5
9 files changed, 184 insertions, 233 deletions
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 637ea159d79..bd95f1b735b 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -16,7 +16,7 @@ use lib::llvm::llvm;
 use lib::llvm::ModuleRef;
 use lib;
 use metadata::common::LinkMeta;
-use metadata::{encoder, csearch, cstore};
+use metadata::{encoder, csearch, cstore, filesearch};
 use middle::trans::context::CrateContext;
 use middle::trans::common::gensym_name;
 use middle::ty;
@@ -497,6 +497,7 @@ pub fn build_link_meta(sess: Session,
     struct ProvidedMetas {
         name: Option<@str>,
         vers: Option<@str>,
+        pkg_id: Option<@str>,
         cmh_items: ~[@ast::MetaItem]
     }
 
@@ -504,6 +505,7 @@ pub fn build_link_meta(sess: Session,
        ProvidedMetas {
         let mut name = None;
         let mut vers = None;
+        let mut pkg_id = None;
         let mut cmh_items = ~[];
         let linkage_metas = attr::find_linkage_metas(c.attrs);
         attr::require_unique_names(sess.diagnostic(), linkage_metas);
@@ -511,6 +513,7 @@ pub fn build_link_meta(sess: Session,
             match meta.name_str_pair() {
                 Some((n, value)) if "name" == n => name = Some(value),
                 Some((n, value)) if "vers" == n => vers = Some(value),
+                Some((n, value)) if "package_id" == n => pkg_id = Some(value),
                 _ => cmh_items.push(*meta)
             }
         }
@@ -518,6 +521,7 @@ pub fn build_link_meta(sess: Session,
         ProvidedMetas {
             name: name,
             vers: vers,
+            pkg_id: pkg_id,
             cmh_items: cmh_items
         }
     }
@@ -525,7 +529,8 @@ pub fn build_link_meta(sess: Session,
     // This calculates CMH as defined above
     fn crate_meta_extras_hash(symbol_hasher: &mut hash::State,
                               cmh_items: ~[@ast::MetaItem],
-                              dep_hashes: ~[@str]) -> @str {
+                              dep_hashes: ~[@str],
+                              pkg_id: Option<@str>) -> @str {
         fn len_and_str(s: &str) -> ~str {
             fmt!("%u_%s", s.len(), s)
         }
@@ -563,7 +568,10 @@ pub fn build_link_meta(sess: Session,
             write_string(symbol_hasher, len_and_str(*dh));
         }
 
-    // tjc: allocation is unfortunate; need to change std::hash
+        for p in pkg_id.iter() {
+            write_string(symbol_hasher, len_and_str(*p));
+        }
+
         return truncated_hash_result(symbol_hasher).to_managed();
     }
 
@@ -605,6 +613,7 @@ pub fn build_link_meta(sess: Session,
     let ProvidedMetas {
         name: opt_name,
         vers: opt_vers,
+        pkg_id: opt_pkg_id,
         cmh_items: cmh_items
     } = provided_link_metas(sess, c);
     let name = crate_meta_name(sess, output, opt_name);
@@ -612,11 +621,12 @@ pub fn build_link_meta(sess: Session,
     let dep_hashes = cstore::get_dep_hashes(sess.cstore);
     let extras_hash =
         crate_meta_extras_hash(symbol_hasher, cmh_items,
-                               dep_hashes);
+                               dep_hashes, opt_pkg_id);
 
     LinkMeta {
         name: name,
         vers: vers,
+        package_id: opt_pkg_id,
         extras_hash: extras_hash
     }
 }
@@ -939,6 +949,11 @@ pub fn link_args(sess: Session,
         args.push(~"-L" + path.to_str());
     }
 
+    let rustpath = filesearch::rust_path();
+    for path in rustpath.iter() {
+        args.push(~"-L" + path.to_str());
+    }
+
     // The names of the extern libraries
     let used_libs = cstore::get_used_libraries(cstore);
     for l in used_libs.iter() { args.push(~"-l" + *l); }
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index 6aac627729c..5dc92dbc5e6 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -14,10 +14,7 @@ use metadata::cstore;
 use metadata::filesearch;
 
 use std::hashmap::HashSet;
-use std::num;
-use std::os;
-use std::util;
-use std::vec;
+use std::{num, os, path, uint, util, vec};
 
 fn not_win32(os: session::os) -> bool {
   os != session::os_win32
@@ -122,42 +119,7 @@ pub fn get_rpath_relative_to_output(os: session::os,
         session::os_win32 => util::unreachable()
     };
 
-    Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
-                                           &os::make_absolute(lib)))
-}
-
-// Find the relative path from one file to another
-pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
-    assert!(abs1.is_absolute);
-    assert!(abs2.is_absolute);
-    let abs1 = abs1.normalize();
-    let abs2 = abs2.normalize();
-    debug!("finding relative path from %s to %s",
-           abs1.to_str(), abs2.to_str());
-    let split1: &[~str] = abs1.components;
-    let split2: &[~str] = abs2.components;
-    let len1 = split1.len();
-    let len2 = split2.len();
-    assert!(len1 > 0);
-    assert!(len2 > 0);
-
-    let max_common_path = num::min(len1, len2) - 1;
-    let mut start_idx = 0;
-    while start_idx < max_common_path
-        && split1[start_idx] == split2[start_idx] {
-        start_idx += 1;
-    }
-
-    let mut path = ~[];
-    for _ in range(start_idx, len1 - 1) { path.push(~".."); };
-
-    path.push_all(split2.slice(start_idx, len2 - 1));
-
-    return if !path.is_empty() {
-        Path("").push_many(path)
-    } else {
-        Path(".")
-    }
+    Path(prefix).push_rel(&os::make_absolute(output).get_relative_to(&os::make_absolute(lib)))
 }
 
 fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
@@ -208,8 +170,7 @@ mod test {
     #[cfg(test)]
     #[cfg(test)]
     use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
-    use back::rpath::{get_relative_to, get_rpath_relative_to_output};
-    use back::rpath::{minimize_rpaths, rpaths_to_flags};
+    use back::rpath::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
     use driver::session;
 
     #[test]
@@ -254,77 +215,8 @@ mod test {
     }
 
     #[test]
-    fn test_relative_to1() {
-        let p1 = Path("/usr/bin/rustc");
-        let p2 = Path("/usr/lib/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib"));
-    }
-
-    #[test]
-    fn test_relative_to2() {
-        let p1 = Path("/usr/bin/rustc");
-        let p2 = Path("/usr/bin/../lib/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib"));
-    }
-
-    #[test]
-    fn test_relative_to3() {
-        let p1 = Path("/usr/bin/whatever/rustc");
-        let p2 = Path("/usr/lib/whatever/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../../lib/whatever"));
-    }
-
-    #[test]
-    fn test_relative_to4() {
-        let p1 = Path("/usr/bin/whatever/../rustc");
-        let p2 = Path("/usr/lib/whatever/mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib/whatever"));
-    }
-
-    #[test]
-    fn test_relative_to5() {
-        let p1 = Path("/usr/bin/whatever/../rustc");
-        let p2 = Path("/usr/lib/whatever/../mylib");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("../lib"));
-    }
-
-    #[test]
-    fn test_relative_to6() {
-        let p1 = Path("/1");
-        let p2 = Path("/2/3");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path("2"));
-    }
-
-    #[test]
-    fn test_relative_to7() {
-        let p1 = Path("/1/2");
-        let p2 = Path("/3");
-        let res = get_relative_to(&p1, &p2);
-        assert_eq!(res, Path(".."));
-    }
-
-    #[test]
-    fn test_relative_to8() {
-        let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
-            &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
-        let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
-            &Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
-        let res = get_relative_to(&p1, &p2);
-        debug!("test_relative_tu8: %s vs. %s",
-               res.to_str(),
-               Path(".").to_str());
-        assert_eq!(res, Path("."));
-    }
-
-    #[test]
     #[cfg(target_os = "linux")]
-    #[cfg(target_os = "andorid")]
+    #[cfg(target_os = "android")]
     fn test_rpath_relative() {
       let o = session::os_linux;
       let res = get_rpath_relative_to_output(o,
@@ -344,7 +236,6 @@ mod test {
     #[test]
     #[cfg(target_os = "macos")]
     fn test_rpath_relative() {
-        // this is why refinements would be nice
         let o = session::os_macos;
         let res = get_rpath_relative_to_output(o,
                                                &Path("bin/rustc"),
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index 3a1129b1dd9..2a61ea28e0c 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -47,7 +47,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
             let n1 = sess.next_node_id();
             let vi1 = ast::view_item {
                 node: ast::view_item_extern_mod(
-                        sess.ident_of("std"), ~[], n1),
+                        sess.ident_of("std"), None, ~[], n1),
                 attrs: ~[
                     attr::mk_attr(
                         attr::mk_name_value_item_str(@"vers", STD_VERSION.to_managed()))
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index d2d2a8b4be9..c6b1bdbe51b 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -282,7 +282,7 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
                                             cx.sess.next_node_id()))])
     } else {
         let mi = attr::mk_name_value_item_str(@"vers", @"0.8-pre");
-        ast::view_item_extern_mod(id_extra, ~[mi], cx.sess.next_node_id())
+        ast::view_item_extern_mod(id_extra, None, ~[mi], cx.sess.next_node_id())
     };
     ast::view_item {
         node: vi,
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 1c5d202d4d9..f2d8b68faa6 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -185,5 +185,7 @@ pub static tag_item_impl_vtables: uint = 0x82;
 pub struct LinkMeta {
     name: @str,
     vers: @str,
+    // Optional package ID
+    package_id: Option<@str>, // non-None if this was a URL-like package ID
     extras_hash: @str
 }
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index d8f14228824..0a9e8490f22 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -18,6 +18,7 @@ use metadata::loader;
 
 use std::hashmap::HashMap;
 use syntax::ast;
+use std::vec;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{span, dummy_sp};
@@ -137,18 +138,33 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
 
 fn visit_view_item(e: @mut Env, i: &ast::view_item) {
     match i.node {
-      ast::view_item_extern_mod(ident, ref meta_items, id) => {
-        debug!("resolving extern mod stmt. ident: %?, meta: %?",
-               ident, *meta_items);
-        let cnum = resolve_crate(e,
-                                 ident,
-                                 (*meta_items).clone(),
-                                 @"",
-                                 i.span);
-        cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
+      ast::view_item_extern_mod(ident, path_opt, ref meta_items, id) => {
+          let ident = token::ident_to_str(&ident);
+          let meta_items = match path_opt {
+              None => meta_items.clone(),
+              Some(p) => {
+                  let p_path = Path(p);
+                  match p_path.filestem() {
+                      Some(s) =>
+                          vec::append(
+                              ~[attr::mk_name_value_item_str(@"package_id", p),
+                               attr::mk_name_value_item_str(@"name", s.to_managed())],
+                              *meta_items),
+                      None => e.diag.span_bug(i.span, "Bad package path in `extern mod` item")
+                  }
+            }
+          };
+          debug!("resolving extern mod stmt. ident: %?, meta: %?",
+                 ident, meta_items);
+          let cnum = resolve_crate(e,
+                                   ident,
+                                   meta_items,
+                                   @"",
+                                   i.span);
+          cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
       }
       _ => ()
-    }
+  }
 }
 
 fn visit_item(e: &Env, i: @ast::item) {
@@ -233,12 +249,12 @@ fn existing_match(e: &Env, metas: &[@ast::MetaItem], hash: &str)
 }
 
 fn resolve_crate(e: @mut Env,
-                 ident: ast::ident,
+                 ident: @str,
                  metas: ~[@ast::MetaItem],
                  hash: @str,
                  span: span)
               -> ast::CrateNum {
-    let metas = metas_with_ident(token::ident_to_str(&ident), metas);
+    let metas = metas_with_ident(ident, metas);
 
     match existing_match(e, metas, hash) {
       None => {
@@ -279,7 +295,7 @@ fn resolve_crate(e: @mut Env,
             match attr::last_meta_item_value_str_by_name(load_ctxt.metas,
                                                          "name") {
                 Some(v) => v,
-                None => token::ident_to_str(&ident),
+                None => ident
             };
         let cmeta = @cstore::crate_metadata {
             name: cname,
@@ -308,7 +324,6 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
     let r = decoder::get_crate_deps(cdata);
     for dep in r.iter() {
         let extrn_cnum = dep.cnum;
-        let cname = dep.name;
         let cname_str = token::ident_to_str(&dep.name);
         let cmetas = metas_with(dep.vers, @"vers", ~[]);
         debug!("resolving dep crate %s ver: %s hash: %s",
@@ -327,7 +342,7 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
             // FIXME (#2404): Need better error reporting than just a bogus
             // span.
             let fake_span = dummy_sp();
-            let local_cnum = resolve_crate(e, cname, cmetas, dep.hash,
+            let local_cnum = resolve_crate(e, cname_str, cmetas, dep.hash,
                                            fake_span);
             cnum_map.insert(extrn_cnum, local_cnum);
           }
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index e18879464e8..2b44d793a9d 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -11,12 +11,15 @@
 
 use std::option;
 use std::os;
-use std::result;
+use std::{result, str};
+use std::hashmap::HashSet;
 
 // A module for searching for libraries
 // FIXME (#2658): I'm not happy how this module turned out. Should
 // probably just be folded into cstore.
 
+/// Functions with type `pick` take a parent directory as well as
+/// a file found in that directory.
 pub type pick<'self, T> = &'self fn(path: &Path) -> Option<T>;
 
 pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
@@ -46,28 +49,33 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
     impl FileSearch for FileSearchImpl {
         fn sysroot(&self) -> @Path { self.sysroot }
         fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool {
+            let mut visited_dirs = HashSet::new();
+
             debug!("filesearch: searching additional lib search paths [%?]",
                    self.addl_lib_search_paths.len());
-            // a little weird
-            self.addl_lib_search_paths.iter().advance(|path| f(path));
+            for path in self.addl_lib_search_paths.iter() {
+                f(path);
+                visited_dirs.insert(path.to_str());
+            }
 
             debug!("filesearch: searching target lib path");
-            if !f(&make_target_lib_path(self.sysroot,
-                                        self.target_triple)) {
-                return false;
-            }
-            debug!("filesearch: searching rustpkg lib path nearest");
-            if match get_rustpkg_lib_path_nearest() {
-                    result::Ok(ref p) => f(p),
-                    result::Err(_) => true
-                } {
-                    return true;
+            let tlib_path = make_target_lib_path(self.sysroot,
+                                        self.target_triple);
+            if !visited_dirs.contains(&tlib_path.to_str()) {
+                if !f(&tlib_path) {
+                    return false;
                 }
-           debug!("filesearch: searching rustpkg lib path");
-           match get_rustpkg_lib_path() {
-              result::Ok(ref p) => f(p),
-              result::Err(_) => true
-           }
+            }
+            visited_dirs.insert(tlib_path.to_str());
+            // Try RUST_PATH
+            let rustpath = rust_path();
+            for path in rustpath.iter() {
+                    if !visited_dirs.contains(&path.push("lib").to_str()) {
+                        f(&path.push("lib"));
+                        visited_dirs.insert(path.push("lib").to_str());
+                    }
+            }
+            true
         }
         fn get_target_lib_path(&self) -> Path {
             make_target_lib_path(self.sysroot, self.target_triple)
@@ -94,12 +102,15 @@ pub fn search<T>(filesearch: @FileSearch, pick: pick<T>) -> Option<T> {
         for path in r.iter() {
             debug!("testing %s", path.to_str());
             let maybe_picked = pick(path);
-            if maybe_picked.is_some() {
-                debug!("picked %s", path.to_str());
-                rslt = maybe_picked;
-                break;
-            } else {
-                debug!("rejected %s", path.to_str());
+            match maybe_picked {
+                Some(_) => {
+                    debug!("picked %s", path.to_str());
+                    rslt = maybe_picked;
+                    break;
+                }
+                None => {
+                    debug!("rejected %s", path.to_str());
+                }
             }
         }
         rslt.is_none()
@@ -132,55 +143,59 @@ fn get_sysroot(maybe_sysroot: &Option<@Path>) -> @Path {
     }
 }
 
-pub fn get_rustpkg_sysroot() -> Result<Path, ~str> {
-    result::Ok(get_or_default_sysroot().push_many([libdir(), ~"rustpkg"]))
+#[cfg(windows)]
+static PATH_ENTRY_SEPARATOR: &'static str = ";";
+#[cfg(not(windows))]
+static PATH_ENTRY_SEPARATOR: &'static str = ":";
+
+/// Returns RUST_PATH as a string, without default paths added
+pub fn get_rust_path() -> Option<~str> {
+    os::getenv("RUST_PATH")
 }
 
-pub fn get_rustpkg_root() -> Result<Path, ~str> {
-    match os::getenv("RUSTPKG_ROOT") {
-        Some(ref _p) => result::Ok(Path((*_p))),
-        None => match os::homedir() {
-          Some(ref _q) => result::Ok((*_q).push(".rustpkg")),
-          None => result::Err(~"no RUSTPKG_ROOT or home directory")
+/// Returns the value of RUST_PATH, as a list
+/// of Paths. Includes default entries for, if they exist:
+/// $HOME/.rust
+/// DIR/.rust for any DIR that's the current working directory
+/// or an ancestor of it
+pub fn rust_path() -> ~[Path] {
+    let mut env_rust_path: ~[Path] = match get_rust_path() {
+        Some(env_path) => {
+            let env_path_components: ~[&str] =
+                env_path.split_str_iter(PATH_ENTRY_SEPARATOR).collect();
+            env_path_components.map(|&s| Path(s))
         }
+        None => ~[]
+    };
+    let cwd = os::getcwd();
+    // now add in default entries
+    let cwd_dot_rust = cwd.push(".rust");
+    if !env_rust_path.contains(&cwd_dot_rust) {
+        env_rust_path.push(cwd_dot_rust);
     }
-}
-
-pub fn get_rustpkg_root_nearest() -> Result<Path, ~str> {
-    do get_rustpkg_root().chain |p| {
-        let cwd = os::getcwd();
-        let cwd_rustpkg = cwd.push(".rustpkg");
-        let rustpkg_is_non_root_file =
-            !os::path_is_dir(&cwd_rustpkg) && cwd_rustpkg != p;
-        let mut par_rustpkg = cwd.pop().push(".rustpkg");
-        let mut rslt = result::Ok(cwd_rustpkg);
-
-        if rustpkg_is_non_root_file {
-            while par_rustpkg != p {
-                if os::path_is_dir(&par_rustpkg) {
-                    rslt = result::Ok(par_rustpkg);
-                    break;
-                }
-                if par_rustpkg.components.len() == 1 {
-                    // We just checked /.rustpkg, stop now.
-                    break;
-                }
-                par_rustpkg = par_rustpkg.pop().pop().push(".rustpkg");
-            }
+    if !env_rust_path.contains(&cwd) {
+        env_rust_path.push(cwd.clone());
+    }
+    do cwd.each_parent() |p| {
+        if !env_rust_path.contains(&p.push(".rust")) {
+            push_if_exists(&mut env_rust_path, p);
         }
-        rslt
     }
-}
-
-fn get_rustpkg_lib_path() -> Result<Path, ~str> {
-    do get_rustpkg_root().chain |p| {
-        result::Ok(p.push(libdir()))
+    let h = os::homedir();
+    for h in h.iter() {
+        if !env_rust_path.contains(&h.push(".rust")) {
+            push_if_exists(&mut env_rust_path, h);
+        }
     }
+    env_rust_path
 }
 
-fn get_rustpkg_lib_path_nearest() -> Result<Path, ~str> {
-    do get_rustpkg_root_nearest().chain |p| {
-        result::Ok(p.push(libdir()))
+
+/// Adds p/.rust into vec, only if it exists
+fn push_if_exists(vec: &mut ~[Path], p: &Path) {
+    let maybe_dir = p.push(".rust");
+    if os::path_exists(&maybe_dir) {
+        vec.push(maybe_dir);
     }
 }
 
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 9330cfc5c88..5f145d87ca8 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -18,7 +18,6 @@ use metadata::filesearch::FileSearch;
 use metadata::filesearch;
 use syntax::codemap::span;
 use syntax::diagnostic::span_handler;
-use syntax::parse::token;
 use syntax::parse::token::ident_interner;
 use syntax::print::pprust;
 use syntax::{ast, attr};
@@ -46,7 +45,7 @@ pub struct Context {
     diag: @span_handler,
     filesearch: @FileSearch,
     span: span,
-    ident: ast::ident,
+    ident: @str,
     metas: ~[@ast::MetaItem],
     hash: @str,
     os: os,
@@ -60,7 +59,7 @@ pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
       None => {
         cx.diag.span_fatal(cx.span,
                            fmt!("can't find crate for `%s`",
-                                token::ident_to_str(&cx.ident)));
+                                cx.ident));
       }
     }
 }
@@ -89,37 +88,38 @@ fn find_library_crate_aux(
     filesearch: @filesearch::FileSearch
 ) -> Option<(~str, @~[u8])> {
     let crate_name = crate_name_from_metas(cx.metas);
-    let prefix = prefix + crate_name + "-";
-
+    // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
+    let prefix = fmt!("%s%s-", prefix, crate_name);
     let mut matches = ~[];
     filesearch::search(filesearch, |path| -> Option<()> {
-        debug!("inspecting file %s", path.to_str());
-        match path.filename() {
-            Some(ref f) if f.starts_with(prefix) && f.ends_with(suffix) => {
-                debug!("%s is a candidate", path.to_str());
-                match get_metadata_section(cx.os, path) {
-                    Some(cvec) =>
-                        if !crate_matches(cvec, cx.metas, cx.hash) {
-                            debug!("skipping %s, metadata doesn't match",
-                                   path.to_str());
-                            None
-                        } else {
-                            debug!("found %s with matching metadata", path.to_str());
-                            matches.push((path.to_str(), cvec));
-                            None
-                        },
-                    _ => {
-                        debug!("could not load metadata for %s", path.to_str());
-                        None
-                    }
-                }
-            }
-            _ => {
-                debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
-                       prefix, suffix);
-                None
-            }
-        }});
+      let path_str = path.filename();
+      match path_str {
+          None => None,
+          Some(path_str) =>
+              if path_str.starts_with(prefix) && path_str.ends_with(suffix) {
+                  debug!("%s is a candidate", path.to_str());
+                  match get_metadata_section(cx.os, path) {
+                      Some(cvec) =>
+                          if !crate_matches(cvec, cx.metas, cx.hash) {
+                              debug!("skipping %s, metadata doesn't match",
+                                  path.to_str());
+                              None
+                          } else {
+                              debug!("found %s with matching metadata", path.to_str());
+                              matches.push((path.to_str(), cvec));
+                              None
+                          },
+                      _ => {
+                          debug!("could not load metadata for %s", path.to_str());
+                          None
+                      }
+                  }
+               }
+               else {
+                   None
+               }
+      }
+    });
 
     match matches.len() {
         0 => None,
@@ -137,8 +137,8 @@ fn find_library_crate_aux(
                 }
                 cx.diag.handler().abort_if_errors();
                 None
-            }
         }
+    }
 }
 
 pub fn crate_name_from_metas(metas: &[@ast::MetaItem]) -> @str {
@@ -151,6 +151,16 @@ pub fn crate_name_from_metas(metas: &[@ast::MetaItem]) -> @str {
     fail!("expected to find the crate name")
 }
 
+pub fn package_id_from_metas(metas: &[@ast::MetaItem]) -> Option<@str> {
+    for m in metas.iter() {
+        match m.name_str_pair() {
+            Some((name, s)) if "package_id" == name => { return Some(s); }
+            _ => {}
+        }
+    }
+    None
+}
+
 pub fn note_linkage_attrs(intr: @ident_interner,
                           diag: @span_handler,
                           attrs: ~[ast::Attribute]) {
@@ -175,6 +185,8 @@ fn crate_matches(crate_data: @~[u8],
 pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
                         local_metas: &[@ast::MetaItem]) -> bool {
 
+// extern_metas: metas we read from the crate
+// local_metas: metas we're looking for
     debug!("matching %u metadata requirements against %u items",
            local_metas.len(), extern_metas.len());
 
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 43953a50e15..7d892d97676 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -1487,9 +1487,10 @@ impl Resolver {
                 }
             }
 
-            view_item_extern_mod(name, _, node_id) => {
+            view_item_extern_mod(name, _, _, node_id) => {
+                // n.b. we don't need to look at the path option here, because cstore already did
                 match find_extern_mod_stmt_cnum(self.session.cstore,
-                                                node_id) {
+                                                        node_id) {
                     Some(crate_id) => {
                         let def_id = def_id { crate: crate_id, node: 0 };
                         let parent_link = ModuleParentLink