about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/clean.rs84
-rw-r--r--src/librustdoc/core.rs11
-rw-r--r--src/librustdoc/html/format.rs61
-rw-r--r--src/librustdoc/html/render.rs88
-rw-r--r--src/librustdoc/passes.rs17
-rw-r--r--src/librustdoc/test.rs3
6 files changed, 140 insertions, 124 deletions
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index 14a27a60782..aef289a4a7f 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -670,15 +670,7 @@ pub enum Type {
     ResolvedPath {
         pub path: Path,
         pub typarams: Option<Vec<TyParamBound>>,
-        pub id: ast::NodeId,
-    },
-    /// Same as above, but only external variants
-    ExternalPath {
-        pub path: Path,
-        pub typarams: Option<Vec<TyParamBound>>,
-        pub fqn: Vec<~str>,
-        pub kind: TypeKind,
-        pub krate: ast::CrateNum,
+        pub did: ast::DefId,
     },
     // I have no idea how to usefully use this.
     TyParamBinder(ast::NodeId),
@@ -715,19 +707,18 @@ pub enum Type {
 
 #[deriving(Clone, Encodable, Decodable)]
 pub enum TypeKind {
-    TypeStruct,
     TypeEnum,
-    TypeTrait,
     TypeFunction,
+    TypeModule,
+    TypeStatic,
+    TypeStruct,
+    TypeTrait,
+    TypeVariant,
 }
 
 impl Clean<Type> for ast::Ty {
     fn clean(&self) -> Type {
         use syntax::ast::*;
-        debug!("cleaning type `{:?}`", self);
-        let ctxt = super::ctxtkey.get().unwrap();
-        let codemap = ctxt.sess().codemap();
-        debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
         match self.node {
             TyNil => Unit,
             TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
@@ -1153,7 +1144,7 @@ pub enum ViewPath {
     // use source::*;
     GlobImport(ImportSource),
     // use source::{a, b, c};
-    ImportList(ImportSource, Vec<ViewListIdent> ),
+    ImportList(ImportSource, Vec<ViewListIdent>),
 }
 
 #[deriving(Clone, Encodable, Decodable)]
@@ -1298,48 +1289,47 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
         core::NotTyped(_) => return Bool
     };
     debug!("searching for {:?} in defmap", id);
-    let d = match tycx.def_map.borrow().find(&id) {
+    let def = match tycx.def_map.borrow().find(&id) {
         Some(&k) => k,
-        None => {
-            debug!("could not find {:?} in defmap (`{}`)", id, tycx.map.node_to_str(id));
-            fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
-        }
+        None => fail!("unresolved id not in defmap")
     };
 
-    let (def_id, kind) = match d {
-        ast::DefFn(i, _) => (i, TypeFunction),
+    match def {
         ast::DefSelfTy(i) => return Self(i),
-        ast::DefTy(i) => (i, TypeEnum),
-        ast::DefTrait(i) => {
-            debug!("saw DefTrait in def_to_id");
-            (i, TypeTrait)
-        },
         ast::DefPrimTy(p) => match p {
             ast::TyStr => return String,
             ast::TyBool => return Bool,
             _ => return Primitive(p)
         },
         ast::DefTyParam(i, _) => return Generic(i.node),
+        ast::DefTyParamBinder(i) => return TyParamBinder(i),
+        _ => {}
+    };
+    let did = register_def(&**cx, def);
+    ResolvedPath { path: path, typarams: tpbs, did: did }
+}
+
+fn register_def(cx: &core::DocContext, def: ast::Def) -> ast::DefId {
+    let (did, kind) = match def {
+        ast::DefFn(i, _) => (i, TypeFunction),
+        ast::DefTy(i) => (i, TypeEnum),
+        ast::DefTrait(i) => (i, TypeTrait),
         ast::DefStruct(i) => (i, TypeStruct),
-        ast::DefTyParamBinder(i) => {
-            debug!("found a typaram_binder, what is it? {}", i);
-            return TyParamBinder(i);
-        },
-        x => fail!("resolved type maps to a weird def {:?}", x),
+        ast::DefMod(i) => (i, TypeModule),
+        ast::DefStatic(i, _) => (i, TypeStatic),
+        ast::DefVariant(i, _, _) => (i, TypeEnum),
+        _ => return ast_util::def_id_of_def(def),
     };
-    if ast_util::is_local(def_id) {
-        ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
-    } else {
-        let fqn = csearch::get_item_path(tycx, def_id);
-        let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
-        ExternalPath {
-            path: path,
-            typarams: tpbs,
-            fqn: fqn,
-            kind: kind,
-            krate: def_id.krate,
-        }
-    }
+    if ast_util::is_local(did) { return did }
+    let tcx = match cx.maybe_typed {
+        core::Typed(ref t) => t,
+        core::NotTyped(_) => return did
+    };
+    let fqn = csearch::get_item_path(tcx, did);
+    let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
+    debug!("recording {} => {}", did, fqn);
+    cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
+    return did;
 }
 
 fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
@@ -1353,7 +1343,7 @@ fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
     let cx = super::ctxtkey.get().unwrap();
     match cx.maybe_typed {
         core::Typed(ref tcx) => {
-            tcx.def_map.borrow().find(&id).map(|&d| ast_util::def_id_of_def(d))
+            tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def))
         }
         core::NotTyped(_) => None
     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 1916e053e98..d65d5a1e458 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -20,7 +20,7 @@ use syntax;
 
 use std::cell::RefCell;
 use std::os;
-use collections::HashSet;
+use collections::{HashSet, HashMap};
 
 use visit_ast::RustdocVisitor;
 use clean;
@@ -31,10 +31,14 @@ pub enum MaybeTyped {
     NotTyped(driver::session::Session)
 }
 
+pub type ExternalPaths = RefCell<Option<HashMap<ast::DefId,
+                                                (Vec<~str>, clean::TypeKind)>>>;
+
 pub struct DocContext {
     pub krate: ast::Crate,
     pub maybe_typed: MaybeTyped,
     pub src: Path,
+    pub external_paths: ExternalPaths,
 }
 
 impl DocContext {
@@ -49,6 +53,7 @@ impl DocContext {
 pub struct CrateAnalysis {
     pub exported_items: privacy::ExportedItems,
     pub public_items: privacy::PublicItems,
+    pub external_paths: ExternalPaths,
 }
 
 /// Parses, resolves, and typechecks the given crate
@@ -98,9 +103,11 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
         krate: krate,
         maybe_typed: Typed(ty_cx),
         src: cpath.clone(),
+        external_paths: RefCell::new(Some(HashMap::new())),
     }, CrateAnalysis {
         exported_items: exported_items,
         public_items: public_items,
+        external_paths: RefCell::new(None),
     })
 }
 
@@ -116,5 +123,7 @@ pub fn run_core(libs: HashSet<Path>, cfgs: Vec<~str>, path: &Path)
         v.clean()
     };
 
+    let external_paths = ctxt.external_paths.borrow_mut().take();
+    *analysis.external_paths.borrow_mut() = external_paths;
     (krate, analysis)
 }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b544c939e93..e13e165a34b 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -146,41 +146,28 @@ impl fmt::Show for clean::Path {
 
 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
 /// rendering function with the necessary arguments for linking to a local path.
-fn resolved_path(w: &mut io::Writer, id: ast::NodeId, p: &clean::Path,
+fn resolved_path(w: &mut io::Writer, did: ast::DefId, p: &clean::Path,
                  print_all: bool) -> fmt::Result {
     path(w, p, print_all,
-        |_cache, loc| { Some("../".repeat(loc.len())) },
+        |cache, loc| {
+            if ast_util::is_local(did) {
+                Some("../".repeat(loc.len()))
+            } else {
+                match *cache.extern_locations.get(&did.krate) {
+                    render::Remote(ref s) => Some(s.clone()),
+                    render::Local => Some("../".repeat(loc.len())),
+                    render::Unknown => None,
+                }
+            }
+        },
         |cache| {
-            match cache.paths.find(&id) {
+            match cache.paths.find(&did) {
                 None => None,
                 Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty))
             }
         })
 }
 
-/// Used when rendering an `ExternalPath` structure. Like `resolved_path` this
-/// will invoke `path` with proper linking-style arguments.
-fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool,
-                 fqn: &[~str], kind: clean::TypeKind,
-                 krate: ast::CrateNum) -> fmt::Result {
-    path(w, p, print_all,
-        |cache, loc| {
-            match *cache.extern_locations.get(&krate) {
-                render::Remote(ref s) => Some(s.clone()),
-                render::Local => Some("../".repeat(loc.len())),
-                render::Unknown => None,
-            }
-        },
-        |_cache| {
-            Some((Vec::from_slice(fqn), match kind {
-                clean::TypeStruct => item_type::Struct,
-                clean::TypeEnum => item_type::Enum,
-                clean::TypeFunction => item_type::Function,
-                clean::TypeTrait => item_type::Trait,
-            }))
-        })
-}
-
 fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
         root: |&render::Cache, &[~str]| -> Option<~str>,
         info: |&render::Cache| -> Option<(Vec<~str> , ItemType)>)
@@ -298,15 +285,9 @@ impl fmt::Show for clean::Type {
                 let m = cache_key.get().unwrap();
                 f.buf.write(m.typarams.get(&id).as_bytes())
             }
-            clean::ResolvedPath{id, typarams: ref tp, path: ref path} => {
-                try!(resolved_path(f.buf, id, path, false));
-                tybounds(f.buf, tp)
-            }
-            clean::ExternalPath{path: ref path, typarams: ref tp,
-                                fqn: ref fqn, kind, krate} => {
-                try!(external_path(f.buf, path, false, fqn.as_slice(), kind,
-                                     krate))
-                tybounds(f.buf, tp)
+            clean::ResolvedPath{ did, ref typarams, ref path} => {
+                try!(resolved_path(f.buf, did, path, false));
+                tybounds(f.buf, typarams)
             }
             clean::Self(..) => f.buf.write("Self".as_bytes()),
             clean::Primitive(prim) => {
@@ -543,10 +524,7 @@ impl fmt::Show for clean::ViewPath {
 impl fmt::Show for clean::ImportSource {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.did {
-            // FIXME: shouldn't be restricted to just local imports
-            Some(did) if ast_util::is_local(did) => {
-                resolved_path(f.buf, did.node, &self.path, true)
-            }
+            Some(did) => resolved_path(f.buf, did, &self.path, true),
             _ => {
                 for (i, seg) in self.path.segments.iter().enumerate() {
                     if i > 0 {
@@ -563,8 +541,7 @@ impl fmt::Show for clean::ImportSource {
 impl fmt::Show for clean::ViewListIdent {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.source {
-            // FIXME: shouldn't be limited to just local imports
-            Some(did) if ast_util::is_local(did) => {
+            Some(did) => {
                 let path = clean::Path {
                     global: false,
                     segments: vec!(clean::PathSegment {
@@ -573,7 +550,7 @@ impl fmt::Show for clean::ViewListIdent {
                         types: Vec::new(),
                     })
                 };
-                resolved_path(f.buf, did.node, &path, false)
+                resolved_path(f.buf, did, &path, false)
             }
             _ => write!(f.buf, "{}", self.name),
         }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index fe80d26d109..9b5b8e4a0a5 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -43,6 +43,7 @@ use std::strbuf::StrBuf;
 use sync::Arc;
 use serialize::json::ToJson;
 use syntax::ast;
+use syntax::ast_util;
 use syntax::attr;
 use syntax::parse::token::InternedString;
 use rustc::util::nodemap::NodeSet;
@@ -50,13 +51,13 @@ use rustc::util::nodemap::NodeSet;
 use clean;
 use doctree;
 use fold::DocFolder;
-use html::item_type;
-use html::item_type::{ItemType, shortty};
 use html::format::{VisSpace, Method, FnStyleSpace};
+use html::highlight;
+use html::item_type::{ItemType, shortty};
+use html::item_type;
 use html::layout;
-use html::markdown;
 use html::markdown::Markdown;
-use html::highlight;
+use html::markdown;
 
 /// Major driving force in all rustdoc rendering. This contains information
 /// about where in the tree-like hierarchy rendering is occurring and controls
@@ -138,7 +139,7 @@ pub struct Cache {
     /// URLs when a type is being linked to. External paths are not located in
     /// this map because the `External` type itself has all the information
     /// necessary.
-    pub paths: HashMap<ast::NodeId, (Vec<~str> , ItemType)>,
+    pub paths: HashMap<ast::DefId, (Vec<~str>, ItemType)>,
 
     /// This map contains information about all known traits of this crate.
     /// Implementations of a crate should inherit the documentation of the
@@ -242,12 +243,26 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
     }
 
     // Crawl the crate to build various caches used for the output
-    let public_items = ::analysiskey.get().map(|a| a.public_items.clone());
-    let public_items = public_items.unwrap_or(NodeSet::new());
+    let analysis = ::analysiskey.get();
+    let public_items = analysis.as_ref().map(|a| a.public_items.clone());
+    let paths = analysis.as_ref().map(|a| {
+        let paths = a.external_paths.borrow_mut().take_unwrap();
+        paths.move_iter().map(|(k, (v, t))| {
+            (k, (v, match t {
+                clean::TypeStruct => item_type::Struct,
+                clean::TypeEnum => item_type::Enum,
+                clean::TypeFunction => item_type::Function,
+                clean::TypeTrait => item_type::Trait,
+                clean::TypeModule => item_type::Module,
+                clean::TypeStatic => item_type::Static,
+                clean::TypeVariant => item_type::Variant,
+            }))
+        }).collect()
+    }).unwrap_or(HashMap::new());
     let mut cache = Cache {
         impls: HashMap::new(),
         typarams: HashMap::new(),
-        paths: HashMap::new(),
+        paths: paths,
         traits: HashMap::new(),
         implementors: HashMap::new(),
         stack: Vec::new(),
@@ -255,7 +270,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
         search_index: Vec::new(),
         extern_locations: HashMap::new(),
         privmod: false,
-        public_items: public_items,
+        public_items: public_items.unwrap_or(NodeSet::new()),
         orphan_methods: Vec::new(),
     };
     cache.stack.push(krate.name.clone());
@@ -269,15 +284,16 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
 
         // Attach all orphan methods to the type's definition if the type
         // has since been learned.
-        for &(ref pid, ref item) in meths.iter() {
-            match paths.find(pid) {
+        for &(pid, ref item) in meths.iter() {
+            let did = ast_util::local_def(pid);
+            match paths.find(&did) {
                 Some(&(ref fqp, _)) => {
                     index.push(IndexItem {
                         ty: shortty(item),
                         name: item.name.clone().unwrap(),
                         path: fqp.slice_to(fqp.len() - 1).connect("::"),
                         desc: shorter(item.doc_value()).to_owned(),
-                        parent: Some(*pid),
+                        parent: Some(pid),
                     });
                 },
                 None => {}
@@ -336,7 +352,8 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
         try!(write!(&mut w, r#"],"paths":["#));
 
         for (i, &nodeid) in pathid_to_nodeid.iter().enumerate() {
-            let &(ref fqp, short) = cache.paths.find(&nodeid).unwrap();
+            let def = ast_util::local_def(nodeid);
+            let &(ref fqp, short) = cache.paths.find(&def).unwrap();
             if i > 0 {
                 try!(write!(&mut w, ","));
             }
@@ -414,6 +431,8 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
 
     for &(n, ref e) in krate.externs.iter() {
         cache.extern_locations.insert(n, extern_location(e, &cx.dst));
+        let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID };
+        cache.paths.insert(did, (Vec::new(), item_type::Module));
     }
 
     // And finally render the whole crate's documentation
@@ -605,7 +624,12 @@ impl DocFolder for Cache {
         match item.inner {
             clean::ImplItem(ref i) => {
                 match i.trait_ {
-                    Some(clean::ResolvedPath{ id, .. }) => {
+                    // FIXME: this is_local() check seems to be losing
+                    // information
+                    Some(clean::ResolvedPath{ did, .. })
+                        if ast_util::is_local(did) =>
+                    {
+                        let id = did.node;
                         let v = self.implementors.find_or_insert_with(id, |_|{
                             Vec::new()
                         });
@@ -642,7 +666,8 @@ impl DocFolder for Cache {
                             (None, None)
                         } else {
                             let last = self.parent_stack.last().unwrap();
-                            let path = match self.paths.find(last) {
+                            let did = ast_util::local_def(*last);
+                            let path = match self.paths.find(&did) {
                                 Some(&(_, item_type::Trait)) =>
                                     Some(self.stack.slice_to(self.stack.len() - 1)),
                                 // The current stack not necessarily has correlation for
@@ -698,10 +723,11 @@ impl DocFolder for Cache {
                 // a reexported item doesn't show up in the `public_items` map,
                 // so we can skip inserting into the paths map if there was
                 // already an entry present and we're not a public item.
-                if !self.paths.contains_key(&item.id) ||
+                let did = ast_util::local_def(item.id);
+                if !self.paths.contains_key(&did) ||
                    self.public_items.contains(&item.id) {
-                    self.paths.insert(item.id,
-                                      (self.stack.clone(), shortty(&item)));
+                    self.paths.insert(did, (self.stack.clone(),
+                                            shortty(&item)));
                 }
             }
             // link variants to their parent enum because pages aren't emitted
@@ -709,7 +735,8 @@ impl DocFolder for Cache {
             clean::VariantItem(..) => {
                 let mut stack = self.stack.clone();
                 stack.pop();
-                self.paths.insert(item.id, (stack, item_type::Enum));
+                self.paths.insert(ast_util::local_def(item.id),
+                                  (stack, item_type::Enum));
             }
             _ => {}
         }
@@ -721,8 +748,13 @@ impl DocFolder for Cache {
             }
             clean::ImplItem(ref i) => {
                 match i.for_ {
-                    clean::ResolvedPath{ id, .. } => {
-                        self.parent_stack.push(id); true
+                    clean::ResolvedPath{ did, .. } => {
+                        if ast_util::is_local(did) {
+                            self.parent_stack.push(did.node);
+                            true
+                        } else {
+                            false
+                        }
                     }
                     _ => false
                 }
@@ -737,8 +769,10 @@ impl DocFolder for Cache {
                 match item {
                     clean::Item{ attrs, inner: clean::ImplItem(i), .. } => {
                         match i.for_ {
-                            clean::ResolvedPath { id, .. } => {
-                                let v = self.impls.find_or_insert_with(id, |_| {
+                            clean::ResolvedPath { did, .. }
+                                if ast_util::is_local(did) =>
+                            {
+                                let v = self.impls.find_or_insert_with(did.node, |_| {
                                     Vec::new()
                                 });
                                 // extract relevant documentation for this impl
@@ -1595,7 +1629,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
         Some(ref ty) => {
             try!(write!(w, "{} for ", *ty));
             match *ty {
-                clean::ResolvedPath { id, .. } => Some(id),
+                clean::ResolvedPath { did, .. } => Some(did),
                 _ => None,
             }
         }
@@ -1634,9 +1668,10 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
     // default methods which weren't overridden in the implementation block.
     match trait_id {
         None => {}
-        Some(id) => {
+        // FIXME: this should work for non-local traits
+        Some(did) if ast_util::is_local(did) => {
             try!({
-                match cache_key.get().unwrap().traits.find(&id) {
+                match cache_key.get().unwrap().traits.find(&did.node) {
                     Some(t) => {
                         for method in t.methods.iter() {
                             let n = method.item().name.clone();
@@ -1653,6 +1688,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
                 Ok(())
             })
         }
+        Some(..) => {}
     }
     try!(write!(w, "</div>"));
     Ok(())
diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs
index 38d1b2a14e1..2ad8be462b2 100644
--- a/src/librustdoc/passes.rs
+++ b/src/librustdoc/passes.rs
@@ -65,9 +65,10 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
         impl<'a> fold::DocFolder for ImplStripper<'a> {
             fn fold_item(&mut self, i: Item) -> Option<Item> {
                 match i.inner {
-                    clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: for_id, .. },
-                                                 .. }) => {
-                        if self.stripped.contains(&for_id) {
+                    clean::ImplItem(clean::Impl{
+                        for_: clean::ResolvedPath{ did, .. }, ..
+                    }) => {
+                        if self.stripped.contains(&did.node) {
                             return None;
                         }
                     }
@@ -146,8 +147,10 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             clean::ModuleItem(..) => {}
 
             // trait impls for private items should be stripped
-            clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: ref for_id, .. }, .. }) => {
-                if !self.exported_items.contains(for_id) {
+            clean::ImplItem(clean::Impl{
+                for_: clean::ResolvedPath{ did, .. }, ..
+            }) => {
+                if !self.exported_items.contains(&did.node) {
                     return None;
                 }
             }
@@ -201,9 +204,9 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
         match i.inner {
             clean::ImplItem(ref imp) => {
                 match imp.trait_ {
-                    Some(clean::ResolvedPath{ id, .. }) => {
+                    Some(clean::ResolvedPath{ did, .. }) => {
                         let ImplStripper(s) = *self;
-                        if !s.contains(&id) {
+                        if !s.contains(&did.node) {
                             return None;
                         }
                     }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 898f5856694..c8a19183485 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -16,7 +16,7 @@ use std::os;
 use std::str;
 use std::strbuf::StrBuf;
 
-use collections::HashSet;
+use collections::{HashSet, HashMap};
 use testing;
 use rustc::back::link;
 use rustc::driver::driver;
@@ -73,6 +73,7 @@ pub fn run(input: &str,
         krate: krate,
         maybe_typed: core::NotTyped(sess),
         src: input_path,
+        external_paths: RefCell::new(Some(HashMap::new())),
     };
     super::ctxtkey.replace(Some(ctx));