about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/creader.rs6
-rw-r--r--src/librustc/metadata/csearch.rs12
-rw-r--r--src/librustc/metadata/cstore.rs28
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 {