diff options
| -rw-r--r-- | src/librustc/metadata/creader.rs | 6 | ||||
| -rw-r--r-- | src/librustc/metadata/csearch.rs | 12 | ||||
| -rw-r--r-- | src/librustc/metadata/cstore.rs | 28 |
3 files changed, 39 insertions, 7 deletions
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 578507296fc..f4561d68906 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -34,6 +34,7 @@ use syntax::codemap::{self, Span, mk_sp, Pos}; use syntax::parse; use syntax::parse::token::InternedString; use syntax::visit; +use syntax::util::small_vector::SmallVector; use ast_map; use log; @@ -263,6 +264,7 @@ impl<'a> CrateReader<'a> { let cmeta = Rc::new( cstore::crate_metadata { name: name.to_string(), + local_path: RefCell::new(SmallVector::zero()), data: metadata, cnum_map: cnum_map, cnum: cnum, @@ -520,12 +522,14 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> { match self.creader.extract_crate_info(i) { Some(info) => { - let (cnum, _, _) = self.creader.resolve_crate(&None, + let (cnum, cmeta, _) = self.creader.resolve_crate(&None, &info.ident, &info.name, None, i.span, PathKind::Crate); + self.ast_map.with_path(i.id, |path| + cmeta.update_local_path(path)); self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); } None => () diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 2a469ed69ef..21d5dac7e5d 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -24,7 +24,6 @@ use syntax::ast; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::diagnostic::expect; -use syntax::parse::token; use std::collections::hash_map::HashMap; @@ -89,11 +88,12 @@ pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem> let cdata = cstore.get_crate_data(def.krate); let path = decoder::get_item_path(&*cdata, def.node); - // FIXME #1920: This path is not always correct if the crate is not linked - // into the root namespace. - let mut r = vec![ast_map::PathMod(token::intern(&cdata.name))]; - r.push_all(&path); - r + cdata.with_local_path(|cpath| { + let mut r = Vec::with_capacity(cpath.len() + path.len()); + r.push_all(cpath); + r.push_all(&path); + r + }) } pub enum FoundAst<'ast> { diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 4941c932ead..08c05b76862 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -28,7 +28,10 @@ use std::path::PathBuf; use flate::Bytes; use syntax::ast; use syntax::codemap; +use syntax::parse::token; use syntax::parse::token::IdentInterner; +use syntax::util::small_vector::SmallVector; +use ast_map; // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external @@ -54,6 +57,7 @@ pub struct ImportedFileMap { pub struct crate_metadata { pub name: String, + pub local_path: RefCell<SmallVector<ast_map::PathElem>>, pub data: MetadataBlob, pub cnum_map: cnum_map, pub cnum: ast::CrateNum, @@ -255,6 +259,30 @@ impl crate_metadata { filemaps } } + pub fn with_local_path<T, F>(&self, f: F) -> T + where F: Fn(&[ast_map::PathElem]) -> T { + let cpath = self.local_path.borrow(); + if cpath.is_empty() { + let name = ast_map::PathMod(token::intern(&self.name)); + f(&[name]) + } else { + f(cpath.as_slice()) + } + } + pub fn update_local_path<'a, 'b>(&self, candidate: ast_map::PathElems<'a, 'b>) { + let mut cpath = self.local_path.borrow_mut(); + let cap = cpath.len(); + match cap { + 0 => *cpath = candidate.collect(), + 1 => (), + _ => { + let candidate: SmallVector<_> = candidate.collect(); + if candidate.len() < cap { + *cpath = candidate; + } + }, + } + } } impl MetadataBlob { |
