about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/common.rs8
-rw-r--r--src/librustc/metadata/creader.rs228
-rw-r--r--src/librustc/metadata/cstore.rs40
-rw-r--r--src/librustc/metadata/decoder.rs40
-rw-r--r--src/librustc/metadata/encoder.rs19
-rw-r--r--src/librustc/metadata/loader.rs54
-rw-r--r--src/librustc/middle/trans/base.rs2
-rw-r--r--src/libsyntax/crateid.rs9
8 files changed, 160 insertions, 240 deletions
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 9cf4df287d2..62f1dcedab4 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -70,12 +70,12 @@ pub static tag_crate_deps: uint = 0x18;
 pub static tag_crate_dep: uint = 0x19;
 
 pub static tag_crate_hash: uint = 0x1a;
+pub static tag_crate_crateid: uint = 0x1b;
 
-pub static tag_parent_item: uint = 0x1b;
+pub static tag_parent_item: uint = 0x1c;
 
-pub static tag_crate_dep_name: uint = 0x1c;
-pub static tag_crate_dep_hash: uint = 0x1d;
-pub static tag_crate_dep_vers: uint = 0x1e;
+pub static tag_crate_dep_crateid: uint = 0x1d;
+pub static tag_crate_dep_hash: uint = 0x1e;
 
 pub static tag_mod_impl: uint = 0x1f;
 
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 9f14b571d82..1108917cdb1 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -79,7 +79,7 @@ struct cache_entry {
     cnum: ast::CrateNum,
     span: Span,
     hash: ~str,
-    crateid: CrateId,
+    crate_id: CrateId,
 }
 
 fn dump_crates(crate_cache: &[cache_entry]) {
@@ -95,10 +95,10 @@ fn warn_if_multiple_versions(e: &mut Env,
                              diag: @SpanHandler,
                              crate_cache: &[cache_entry]) {
     if crate_cache.len() != 0u {
-        let name = crate_cache[crate_cache.len() - 1].crateid.name.clone();
+        let name = crate_cache[crate_cache.len() - 1].crate_id.name.clone();
 
         let (matches, non_matches) = crate_cache.partitioned(|entry|
-            name == entry.crateid.name);
+            name == entry.crate_id.name);
 
         assert!(!matches.is_empty());
 
@@ -107,7 +107,7 @@ fn warn_if_multiple_versions(e: &mut Env,
                 format!("using multiple versions of crate `{}`", name));
             for match_ in matches.iter() {
                 diag.span_note(match_.span, "used here");
-                loader::note_crateid_attr(diag, &match_.crateid);
+                loader::note_crateid_attr(diag, &match_.crate_id);
             }
         }
 
@@ -146,14 +146,9 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
         return;
     }
 
-    match extract_crate_info(i) {
+    match extract_crate_info(e, i) {
         Some(info) => {
-            let cnum = resolve_crate(e,
-                                     None,
-                                     info.ident.clone(),
-                                     info.name.clone(),
-                                     info.version.clone(),
-                                     ~"",
+            let cnum = resolve_crate(e, None, info.ident, &info.crate_id, "",
                                      i.span);
             e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
         }
@@ -163,38 +158,33 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
 
 struct CrateInfo {
     ident: ~str,
-    name: ~str,
-    version: ~str,
+    crate_id: CrateId,
     id: ast::NodeId,
 }
 
-fn extract_crate_info(i: &ast::ViewItem) -> Option<CrateInfo> {
+fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
     match i.node {
         ast::ViewItemExternMod(ident, ref path_opt, id) => {
             let ident = token::get_ident(ident);
             debug!("resolving extern crate stmt. ident: {:?} path_opt: {:?}",
                    ident, path_opt);
-            let (name, version) = match *path_opt {
+            let crate_id = match *path_opt {
                 Some((ref path_str, _)) => {
                     let crateid: Option<CrateId> = from_str(path_str.get());
                     match crateid {
-                        None => (~"", ~""),
-                        Some(crateid) => {
-                            let version = match crateid.version {
-                                None => ~"",
-                                Some(ref ver) => ver.to_str(),
-                            };
-                            (crateid.name.to_str(), version)
+                        None => {
+                            e.sess.span_err(i.span, "malformed crate id");
+                            return None
                         }
+                        Some(id) => id
                     }
                 }
-                None => (ident.get().to_str(), ~""),
+                None => from_str(ident.get().to_str()).unwrap()
             };
             Some(CrateInfo {
-                  ident: ident.get().to_str(),
-                  name: name,
-                  version: version,
-                  id: id,
+                ident: ident.get().to_str(),
+                crate_id: crate_id,
+                id: id,
             })
         }
         _ => None
@@ -285,100 +275,93 @@ fn visit_item(e: &Env, i: &ast::Item) {
     }
 }
 
-fn existing_match(e: &Env, name: &str, version: &str, hash: &str) -> Option<ast::CrateNum> {
+fn existing_match(e: &Env, crate_id: &CrateId,
+                  hash: &str) -> Option<ast::CrateNum> {
     let crate_cache = e.crate_cache.borrow();
     for c in crate_cache.get().iter() {
-        let crateid_version = match c.crateid.version {
-            None => ~"0.0",
-            Some(ref ver) => ver.to_str(),
-        };
-        if (name.is_empty() || name == c.crateid.name) &&
-            (version.is_empty() || version == crateid_version) &&
-            (hash.is_empty() || hash == c.hash) {
-            return Some(c.cnum);
+        if crate_id.matches(&c.crate_id) &&
+           (hash.is_empty() || hash == c.hash.as_slice()) {
+            return Some(c.cnum)
         }
     }
     None
 }
 
 fn resolve_crate(e: &mut Env,
-                 root_ident: Option<~str>,
-                 ident: ~str,
-                 name: ~str,
-                 version: ~str,
-                 hash: ~str,
+                 root_ident: Option<&str>,
+                 ident: &str,
+                 crate_id: &CrateId,
+                 hash: &str,
                  span: Span)
               -> ast::CrateNum {
-    match existing_match(e, name, version, hash) {
-      None => {
-        let load_ctxt = loader::Context {
-            sess: e.sess,
-            span: span,
-            ident: ident,
-            name: name,
-            version: version,
-            hash: hash,
-            os: e.os,
-            intr: e.intr
-        };
-        let loader::Library {
-            dylib, rlib, metadata
-        } = load_ctxt.load_library_crate(root_ident.clone());
-
-        let attrs = decoder::get_crate_attributes(metadata.as_slice());
-        let crateid = attr::find_crateid(attrs).unwrap();
-        let hash = decoder::get_crate_hash(metadata.as_slice());
-
-        // Claim this crate number and cache it
-        let cnum = e.next_crate_num;
-        {
-            let mut crate_cache = e.crate_cache.borrow_mut();
-            crate_cache.get().push(cache_entry {
-                cnum: cnum,
+    match existing_match(e, crate_id, hash) {
+        None => {
+            let load_ctxt = loader::Context {
+                sess: e.sess,
                 span: span,
+                ident: ident,
+                crate_id: crate_id,
                 hash: hash,
-                crateid: crateid,
-            });
-        }
-        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()
-        };
+                os: e.os,
+                intr: e.intr
+            };
+            let loader::Library {
+                dylib, rlib, metadata
+            } = load_ctxt.load_library_crate(root_ident);
+
+            let crate_id = decoder::get_crate_id(metadata.as_slice());
+            let hash = decoder::get_crate_hash(metadata.as_slice());
+
+            // Claim this crate number and cache it
+            let cnum = e.next_crate_num;
+            {
+                let mut crate_cache = e.crate_cache.borrow_mut();
+                crate_cache.get().push(cache_entry {
+                    cnum: cnum,
+                    span: span,
+                    hash: hash,
+                    crate_id: crate_id,
+                });
+            }
+            e.next_crate_num += 1;
 
-        // Now resolve the crates referenced by this crate
-        let cnum_map = resolve_crate_deps(e,
-                                          Some(root_crate),
-                                          metadata.as_slice(),
-                                          span);
+            // Maintain a reference to the top most crate.
+            let root_crate = match root_ident {
+                Some(c) => c,
+                None => load_ctxt.ident.clone()
+            };
 
-        let cmeta = @cstore::crate_metadata {
-            name: load_ctxt.name,
-            data: metadata,
-            cnum_map: cnum_map,
-            cnum: cnum
-        };
+            // Now resolve the crates referenced by this crate
+            let cnum_map = resolve_crate_deps(e,
+            Some(root_crate),
+            metadata.as_slice(),
+            span);
+
+            let cmeta = @cstore::crate_metadata {
+                name: load_ctxt.crate_id.name.to_owned(),
+                data: metadata,
+                cnum_map: cnum_map,
+                cnum: cnum
+            };
 
-        let cstore = e.sess.cstore;
-        cstore.set_crate_data(cnum, cmeta);
-        cstore.add_used_crate_source(cstore::CrateSource {
-            dylib: dylib,
-            rlib: rlib,
-            cnum: cnum,
-        });
-        return cnum;
-      }
-      Some(cnum) => {
-        return cnum;
-      }
+            let cstore = e.sess.cstore;
+            cstore.set_crate_data(cnum, cmeta);
+            cstore.add_used_crate_source(cstore::CrateSource {
+                dylib: dylib,
+                rlib: rlib,
+                cnum: cnum,
+            });
+            return cnum;
+        }
+        Some(cnum) => {
+            return cnum;
+        }
     }
 }
 
 // Go through the crate metadata and load any crates that it references
 fn resolve_crate_deps(e: &mut Env,
-                      root_ident: Option<~str>,
+                      root_ident: Option<&str>,
                       cdata: &[u8], span : Span)
                    -> cstore::cnum_map {
     debug!("resolving deps of external crate");
@@ -388,31 +371,13 @@ fn resolve_crate_deps(e: &mut Env,
     let r = decoder::get_crate_deps(cdata);
     for dep in r.iter() {
         let extrn_cnum = dep.cnum;
-        let cname_str = token::get_ident(dep.name);
-        debug!("resolving dep crate {} ver: {} hash: {}",
-               cname_str, dep.vers, dep.hash);
-        match existing_match(e,
-                             cname_str.get(),
-                             dep.vers,
-                             dep.hash) {
-          Some(local_cnum) => {
-            debug!("already have it");
-            // We've already seen this crate
-            cnum_map.insert(extrn_cnum, local_cnum);
-          }
-          None => {
-            debug!("need to load it");
-            // This is a new one so we've got to load it
-            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(),
-                                           span);
-            cnum_map.insert(extrn_cnum, local_cnum);
-          }
-        }
+        debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
+        let local_cnum = resolve_crate(e, root_ident,
+                                       dep.crate_id.name.as_slice(),
+                                       &dep.crate_id,
+                                       dep.hash,
+                                       span);
+        cnum_map.insert(extrn_cnum, local_cnum);
     }
     return @RefCell::new(cnum_map);
 }
@@ -439,14 +404,9 @@ impl Loader {
 
 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(),
-                                 ~"",
-                                 krate.span);
+        let info = extract_crate_info(&self.env, krate).unwrap();
+        let cnum = resolve_crate(&mut self.env, None, info.ident,
+                                 &info.crate_id, "", krate.span);
         let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
         MacroCrate {
             lib: library.dylib,
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index ce6b5af8d0e..12461ddbe71 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -21,6 +21,7 @@ use collections::HashMap;
 use extra::c_vec::CVec;
 use syntax::ast;
 use syntax::parse::token::IdentInterner;
+use syntax::crateid::CrateId;
 
 // A map from external crate numbers (as decoded from some crate file) to
 // local crate numbers (as generated during this session). Each external
@@ -96,9 +97,9 @@ impl CStore {
         decoder::get_crate_hash(cdata.data())
     }
 
-    pub fn get_crate_vers(&self, cnum: ast::CrateNum) -> ~str {
+    pub fn get_crate_id(&self, cnum: ast::CrateNum) -> CrateId {
         let cdata = self.get_crate_data(cnum);
-        decoder::get_crate_vers(cdata.data())
+        decoder::get_crate_id(cdata.data())
     }
 
     pub fn set_crate_data(&self, cnum: ast::CrateNum, data: @crate_metadata) {
@@ -191,41 +192,6 @@ impl CStore {
         let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
         extern_mod_crate_map.get().find(&emod_id).map(|x| *x)
     }
-
-    // returns hashes of crates directly used by this crate. Hashes are sorted by
-    // (crate name, crate version, crate hash) in lexicographic order (not semver)
-    pub fn get_dep_hashes(&self) -> ~[~str] {
-        let mut result = ~[];
-
-        let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
-        for (_, &cnum) in extern_mod_crate_map.get().iter() {
-            let cdata = self.get_crate_data(cnum);
-            let hash = decoder::get_crate_hash(cdata.data());
-            let vers = decoder::get_crate_vers(cdata.data());
-            debug!("Add hash[{}]: {} {}", cdata.name, vers, hash);
-            result.push(crate_hash {
-                name: cdata.name.clone(),
-                vers: vers,
-                hash: hash
-            });
-        }
-
-        result.sort();
-
-        debug!("sorted:");
-        for x in result.iter() {
-            debug!("  hash[{}]: {}", x.name, x.hash);
-        }
-
-        result.move_iter().map(|crate_hash { hash, ..}| hash).collect()
-    }
-}
-
-#[deriving(Clone, TotalEq, TotalOrd)]
-struct crate_hash {
-    name: ~str,
-    vers: ~str,
-    hash: ~str,
 }
 
 impl crate_metadata {
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index f9f55fbc1bb..f365ddef94f 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -17,7 +17,6 @@ use metadata::common::*;
 use metadata::csearch::StaticMethodInfo;
 use metadata::csearch;
 use metadata::cstore;
-use metadata::decoder;
 use metadata::tydecode::{parse_ty_data, parse_def_id,
                          parse_type_param_def_data,
                          parse_bare_fn_ty_data, parse_trait_ref_data};
@@ -44,6 +43,7 @@ use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::ast;
 use syntax::codemap;
+use syntax::crateid::CrateId;
 
 type Cmd = @crate_metadata;
 
@@ -1108,9 +1108,8 @@ pub fn get_crate_attributes(data: &[u8]) -> ~[ast::Attribute] {
 #[deriving(Clone)]
 pub struct CrateDep {
     cnum: ast::CrateNum,
-    name: ast::Ident,
-    vers: ~str,
-    hash: ~str
+    crate_id: CrateId,
+    hash: ~str,
 }
 
 pub fn get_crate_deps(data: &[u8]) -> ~[CrateDep] {
@@ -1123,10 +1122,13 @@ pub fn get_crate_deps(data: &[u8]) -> ~[CrateDep] {
         d.as_str_slice().to_str()
     }
     reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| {
-        deps.push(CrateDep {cnum: crate_num,
-                  name: token::str_to_ident(docstr(depdoc, tag_crate_dep_name)),
-                  vers: docstr(depdoc, tag_crate_dep_vers),
-                  hash: docstr(depdoc, tag_crate_dep_hash)});
+        let crate_id = from_str(docstr(depdoc, tag_crate_dep_crateid)).unwrap();
+        let hash = docstr(depdoc, tag_crate_dep_hash);
+        deps.push(CrateDep {
+            cnum: crate_num,
+            crate_id: crate_id,
+            hash: hash,
+        });
         crate_num += 1;
         true
     });
@@ -1135,17 +1137,9 @@ pub fn get_crate_deps(data: &[u8]) -> ~[CrateDep] {
 
 fn list_crate_deps(data: &[u8], out: &mut io::Writer) -> io::IoResult<()> {
     try!(write!(out, "=External Dependencies=\n"));
-
-    let r = get_crate_deps(data);
-    for dep in r.iter() {
-        try!(write!(out,
-                      "{} {}-{}-{}\n",
-                      dep.cnum,
-                      token::get_ident(dep.name),
-                      dep.hash,
-                      dep.vers));
+    for dep in get_crate_deps(data).iter() {
+        try!(write!(out, "{} {}-{}\n", dep.cnum, dep.crate_id, dep.hash));
     }
-
     try!(write!(out, "\n"));
     Ok(())
 }
@@ -1156,12 +1150,10 @@ pub fn get_crate_hash(data: &[u8]) -> ~str {
     hashdoc.as_str_slice().to_str()
 }
 
-pub fn get_crate_vers(data: &[u8]) -> ~str {
-    let attrs = decoder::get_crate_attributes(data);
-    match attr::find_crateid(attrs) {
-        None => ~"0.0",
-        Some(crateid) => crateid.version_or_default().to_str(),
-    }
+pub fn get_crate_id(data: &[u8]) -> CrateId {
+    let cratedoc = reader::Doc(data);
+    let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid);
+    from_str(hashdoc.as_str_slice()).unwrap()
 }
 
 pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Writer) -> io::IoResult<()> {
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 285a7411270..976c1ee92d3 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -40,6 +40,7 @@ use syntax::ast_util::*;
 use syntax::ast_util;
 use syntax::attr::AttrMetaMethods;
 use syntax::attr;
+use syntax::crateid::CrateId;
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token::InternedString;
 use syntax::parse::token::special_idents;
@@ -1510,8 +1511,7 @@ fn encode_crate_deps(ebml_w: &mut writer::Encoder, cstore: &cstore::CStore) {
         cstore.iter_crate_data(|key, val| {
             let dep = decoder::CrateDep {
                 cnum: key,
-                name: token::str_to_ident(val.name),
-                vers: decoder::get_crate_vers(val.data()),
+                crate_id: decoder::get_crate_id(val.data()),
                 hash: decoder::get_crate_hash(val.data())
             };
             deps.push(dep);
@@ -1729,12 +1729,8 @@ fn encode_misc_info(ecx: &EncodeContext,
 fn encode_crate_dep(ebml_w: &mut writer::Encoder,
                     dep: decoder::CrateDep) {
     ebml_w.start_tag(tag_crate_dep);
-    ebml_w.start_tag(tag_crate_dep_name);
-    let s = token::get_ident(dep.name);
-    ebml_w.writer.write(s.get().as_bytes());
-    ebml_w.end_tag();
-    ebml_w.start_tag(tag_crate_dep_vers);
-    ebml_w.writer.write(dep.vers.as_bytes());
+    ebml_w.start_tag(tag_crate_dep_crateid);
+    ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
     ebml_w.end_tag();
     ebml_w.start_tag(tag_crate_dep_hash);
     ebml_w.writer.write(dep.hash.as_bytes());
@@ -1748,6 +1744,12 @@ fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
     ebml_w.end_tag();
 }
 
+fn encode_crate_id(ebml_w: &mut writer::Encoder, crate_id: &CrateId) {
+    ebml_w.start_tag(tag_crate_crateid);
+    ebml_w.writer.write(crate_id.to_str().as_bytes());
+    ebml_w.end_tag();
+}
+
 // NB: Increment this as you change the metadata encoding version.
 pub static metadata_encoding_version : &'static [u8] =
     &[0x72, //'r' as u8,
@@ -1806,6 +1808,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
 
     let mut ebml_w = writer::Encoder(wr);
 
+    encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
     encode_hash(&mut ebml_w, ecx.link_meta.crate_hash);
 
     let mut i = ebml_w.writer.tell().unwrap();
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 1f5b76953dc..faef2412e78 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -44,13 +44,12 @@ pub enum Os {
     OsFreebsd
 }
 
-pub struct Context {
+pub struct Context<'a> {
     sess: Session,
     span: Span,
-    ident: ~str,
-    name: ~str,
-    version: ~str,
-    hash: ~str,
+    ident: &'a str,
+    crate_id: &'a CrateId,
+    hash: &'a str,
     os: Os,
     intr: @IdentInterner
 }
@@ -79,8 +78,8 @@ fn realpath(p: &Path) -> Path {
     }
 }
 
-impl Context {
-    pub fn load_library_crate(&self, root_ident: Option<~str>) -> Library {
+impl<'a> Context<'a> {
+    pub fn load_library_crate(&self, root_ident: Option<&str>) -> Library {
         match self.find_library_crate() {
             Some(t) => t,
             None => {
@@ -101,8 +100,8 @@ impl Context {
         let (dyprefix, dysuffix) = self.dylibname();
 
         // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
-        let dylib_prefix = format!("{}{}-", dyprefix, self.name);
-        let rlib_prefix = format!("lib{}-", self.name);
+        let dylib_prefix = format!("{}{}-", dyprefix, self.crate_id.name);
+        let rlib_prefix = format!("lib{}-", self.crate_id.name);
 
         let mut candidates = HashMap::new();
 
@@ -196,7 +195,8 @@ impl Context {
             1 => Some(libraries[0]),
             _ => {
                 self.sess.span_err(self.span,
-                    format!("multiple matching crates for `{}`", self.name));
+                    format!("multiple matching crates for `{}`",
+                            self.crate_id.name));
                 self.sess.note("candidates:");
                 for lib in libraries.iter() {
                     match lib.dylib {
@@ -243,11 +243,12 @@ impl Context {
         debug!("matching -- {}, hash: {}", file, hash);
         let vers = match parts.next() { Some(v) => v, None => return None };
         debug!("matching -- {}, vers: {}", file, vers);
-        if !self.version.is_empty() && self.version.as_slice() != vers {
-            return None
+        match self.crate_id.version {
+            Some(ref version) if version.as_slice() != vers => return None,
+            Some(..) | None => {}
         }
         debug!("matching -- {}, vers ok (requested {})", file,
-               self.version);
+               self.crate_id.version);
         // hashes in filenames are prefixes of the "true hash"
         if self.hash.is_empty() || self.hash.starts_with(hash) {
             debug!("matching -- {}, hash ok (requested {})", file, self.hash);
@@ -275,7 +276,7 @@ impl Context {
         if m.len() > 1 {
             self.sess.span_err(self.span,
                                format!("multiple {} candidates for `{}` \
-                                        found", flavor, self.name));
+                                        found", flavor, self.crate_id.name));
             for (i, path) in m.iter().enumerate() {
                 self.sess.span_note(self.span,
                                     format!(r"candidate \#{}: {}", i + 1,
@@ -289,8 +290,7 @@ impl Context {
             info!("{} reading meatadata from: {}", flavor, lib.display());
             match get_metadata_section(self.os, &lib) {
                 Some(blob) => {
-                    if crate_matches(blob.as_slice(), self.name,
-                                     self.version, self.hash) {
+                    if crate_matches(blob.as_slice(), self.crate_id, self.hash){
                         *slot = Some(blob);
                     } else {
                         info!("metadata mismatch");
@@ -323,23 +323,13 @@ pub fn note_crateid_attr(diag: @SpanHandler, crateid: &CrateId) {
     diag.handler().note(format!("crate_id: {}", crateid.to_str()));
 }
 
-fn crate_matches(crate_data: &[u8],
-                 name: &str,
-                 version: &str,
-                 hash: &str) -> bool {
-    let attrs = decoder::get_crate_attributes(crate_data);
-    match attr::find_crateid(attrs) {
-        None => false,
-        Some(crateid) => {
-            if !hash.is_empty() {
-                let chash = decoder::get_crate_hash(crate_data);
-                if chash.as_slice() != hash { return false; }
-            }
-            name == crateid.name &&
-                (version.is_empty() ||
-                 crateid.version_or_default() == version)
-        }
+fn crate_matches(crate_data: &[u8], crate_id: &CrateId, hash: &str) -> bool {
+    let other_id = decoder::get_crate_id(crate_data);
+    if !crate_id.matches(&other_id) { return false }
+    if hash != "" && hash != decoder::get_crate_hash(crate_data).as_slice() {
+        return false
     }
+    return true;
 }
 
 impl ArchiveMetadata {
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 6a7694b2b81..553dbe2ae6e 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2488,7 +2488,7 @@ pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) {
         let cdata = cstore.get_crate_data(i);
         let nm = symname(format!("_rust_crate_map_{}", cdata.name),
                          cstore.get_crate_hash(i),
-                         cstore.get_crate_vers(i));
+                         cstore.get_crate_id(i).version_or_default());
         let cr = nm.with_c_str(|buf| {
             unsafe {
                 llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
diff --git a/src/libsyntax/crateid.rs b/src/libsyntax/crateid.rs
index 659cd13c94d..b5f02fb7e64 100644
--- a/src/libsyntax/crateid.rs
+++ b/src/libsyntax/crateid.rs
@@ -107,6 +107,15 @@ impl CrateId {
     pub fn short_name_with_version(&self) -> ~str {
         format!("{}-{}", self.name, self.version_or_default())
     }
+
+    pub fn matches(&self, other: &CrateId) -> bool {
+        // FIXME: why does this not match on `path`?
+        if self.name != other.name { return false }
+        match (&self.version, &other.version) {
+            (&Some(ref v1), &Some(ref v2)) => v1 == v2,
+            _ => true,
+        }
+    }
 }
 
 #[test]