]> git.lizzy.rs Git - rust.git/commitdiff
allow retracing paths across crates
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 6 May 2016 18:52:57 +0000 (14:52 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 18 May 2016 14:11:36 +0000 (10:11 -0400)
For external crates, we must build up a map that goes from
the DefKey to the DefIndex. We do this by iterating over each
index that is found in the metadata and loading the associated
DefKey.

src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/middle/cstore.rs
src/librustc/ty/context.rs
src/librustc_incremental/persist/directory.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/csearch.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/decoder.rs

index 358301ab4042a2f3a085287cc6268da8916de59a..457511cdbc3b17057283d670b8df41f2f84b6946 100644 (file)
@@ -82,8 +82,10 @@ pub fn make<FN>(start_krate: ast::CrateNum,
         let mut data = vec![];
         let mut index = Some(start_index);
         loop {
+            debug!("DefPath::make: krate={:?} index={:?}", krate, index);
             let p = index.unwrap();
             let key = get_key(p);
+            debug!("DefPath::make: key={:?}", key);
             match key.disambiguated_data.data {
                 DefPathData::CrateRoot => {
                     assert!(key.parent.is_none());
@@ -178,6 +180,10 @@ pub fn def_key(&self, index: DefIndex) -> DefKey {
         self.data[index.as_usize()].key.clone()
     }
 
+    pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
+        self.key_map.get(&key).cloned()
+    }
+
     /// Returns the path from the crate root to `index`. The root
     /// nodes are not included in the path (i.e., this will be an
     /// empty vector for the crate root). For an inlined item, this
@@ -208,37 +214,6 @@ pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
         }
     }
 
-    pub fn retrace_path(&self, path: &DefPath) -> Option<DefIndex> {
-        debug!("retrace_path(path={:?})", path);
-
-        // we assume that we only want to retrace paths relative to
-        // the crate root
-        assert!(path.is_local());
-
-        let root_key = DefKey {
-            parent: None,
-            disambiguated_data: DisambiguatedDefPathData {
-                data: DefPathData::CrateRoot,
-                disambiguator: 0,
-            },
-        };
-        let root_id = self.key_map[&root_key];
-
-        debug!("retrace_path: root_id={:?}", root_id);
-
-        let mut id = root_id;
-        for data in &path.data {
-            let key = DefKey { parent: Some(id), disambiguated_data: data.clone() };
-            debug!("key = {:?}", key);
-            id = match self.key_map.get(&key) {
-                Some(&id) => id,
-                None => return None
-            };
-        }
-
-        Some(id)
-    }
-
     pub fn create_def_with_parent(&mut self,
                                   parent: Option<DefIndex>,
                                   node_id: ast::NodeId,
index e3976482dca81e31c97c1300b1470a27f8129741..2f310806a7420fa068b4d71ffeec5f661627d415 100644 (file)
@@ -19,7 +19,7 @@
 
 use middle::cstore::InlinedItem;
 use middle::cstore::InlinedItem as II;
-use hir::def_id::{CRATE_DEF_INDEX, DefId};
+use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
 
 use syntax::abi::Abi;
 use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
@@ -285,9 +285,8 @@ pub fn def_path(&self, def_id: DefId) -> DefPath {
         self.definitions.borrow().def_path(def_id.index)
     }
 
-    pub fn retrace_path(&self, path: &DefPath) -> Option<DefId> {
-        self.definitions.borrow().retrace_path(path)
-                                 .map(DefId::local)
+    pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option<DefIndex> {
+        self.definitions.borrow().def_index_for_def_key(def_key)
     }
 
     pub fn local_def_id(&self, node: NodeId) -> DefId {
index 17c6442c019b87a8e43dfc0e3c9645234ebddb21..e5a8c1d1b4e6fe3542aee6b7446651c327c5bfcc 100644 (file)
 // are *mostly* used as a part of that interface, but these should
 // probably get a better home if someone can find one.
 
-use hir::svh::Svh;
-use hir::map as hir_map;
 use hir::def::{self, Def};
+use hir::def_id::{DefId, DefIndex};
+use hir::map as hir_map;
+use hir::map::definitions::DefKey;
+use hir::svh::Svh;
 use middle::lang_items;
 use ty::{self, Ty, TyCtxt, VariantKind};
-use hir::def_id::{DefId, DefIndex};
 use mir::repr::Mir;
 use mir::mir_map::MirMap;
 use session::Session;
@@ -234,6 +235,10 @@ fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
     fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId>;
 
     // resolve
+    fn def_index_for_def_key(&self,
+                             cnum: ast::CrateNum,
+                             def: DefKey)
+                             -> Option<DefIndex>;
     fn def_key(&self, def: DefId) -> hir_map::DefKey;
     fn relative_def_path(&self, def: DefId) -> hir_map::DefPath;
     fn variant_kind(&self, def_id: DefId) -> Option<VariantKind>;
@@ -361,6 +366,12 @@ fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                   -> Vec<Rc<ty::Method<'tcx>>> { bug!("provided_trait_methods") }
     fn trait_item_def_ids(&self, def: DefId)
                           -> Vec<ty::ImplOrTraitItemId> { bug!("trait_item_def_ids") }
+    fn def_index_for_def_key(&self,
+                             cnum: ast::CrateNum,
+                             def: DefKey)
+                             -> Option<DefIndex> {
+        None
+    }
 
     // impl info
     fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
index 39fe744c67d01528f865e96728918c589d6e2b45..ea169b1d3b65325d30e3b4fdc1475267685e713c 100644 (file)
 //! type context book-keeping
 
 use dep_graph::{DepGraph, DepTrackingMap};
-use hir::map as ast_map;
 use session::Session;
 use lint;
 use middle;
 use middle::cstore::LOCAL_CRATE;
 use hir::def::DefMap;
-use hir::def_id::DefId;
+use hir::def_id::{DefId, DefIndex};
+use hir::map as ast_map;
+use hir::map::{DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
 use middle::free_region::FreeRegionMap;
 use middle::region::RegionMaps;
 use middle::resolve_lifetime;
@@ -511,6 +512,49 @@ pub fn crate_disambiguator(self, cnum: ast::CrateNum) -> token::InternedString {
         }
     }
 
+    /// Given a def-key `key` and a crate `krate`, finds the def-index
+    /// that `krate` assigned to `key`. This `DefIndex` will always be
+    /// relative to `krate`.
+    ///
+    /// Returns `None` if there is no `DefIndex` with that key.
+    pub fn def_index_for_def_key(self, krate: ast::CrateNum, key: DefKey)
+                                 -> Option<DefIndex> {
+        if krate == LOCAL_CRATE {
+            self.map.def_index_for_def_key(key)
+        } else {
+            self.sess.cstore.def_index_for_def_key(krate, key)
+        }
+    }
+
+    pub fn retrace_path(self, path: &DefPath) -> Option<DefId> {
+        debug!("retrace_path(path={:?})", path);
+
+        let root_key = DefKey {
+            parent: None,
+            disambiguated_data: DisambiguatedDefPathData {
+                data: DefPathData::CrateRoot,
+                disambiguator: 0,
+            },
+        };
+
+        let root_index = self.def_index_for_def_key(path.krate, root_key)
+                             .expect("no root key?");
+
+        debug!("retrace_path: root_index={:?}", root_index);
+
+        let mut index = root_index;
+        for data in &path.data {
+            let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
+            debug!("retrace_path: key={:?}", key);
+            match self.def_index_for_def_key(path.krate, key) {
+                Some(i) => index = i,
+                None => return None,
+            }
+        }
+
+        Some(DefId { krate: path.krate, index: index })
+    }
+
     pub fn type_parameter_def(self,
                               node_id: NodeId)
                               -> ty::TypeParameterDef<'tcx>
index e256b7cf7d0e111099bd2d751a6abb84b56fe528..0775315875367173cb996bd6aa0014bec9cf636a 100644 (file)
@@ -41,7 +41,7 @@ pub fn new() -> DefIdDirectory {
 
     pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
         let ids = self.paths.iter()
-                            .map(|path| tcx.map.retrace_path(path))
+                            .map(|path| tcx.retrace_path(path))
                             .collect();
         RetracedDefIdDirectory { ids: ids }
     }
index 63c6af704bbfe6b64357447c6f59c29edfa9561a..0eacc0907bc25b2ce151cb6938a7a435009675dd 100644 (file)
@@ -319,6 +319,7 @@ fn register_crate(&mut self,
             extern_crate: Cell::new(None),
             index: decoder::load_index(metadata.as_slice()),
             xref_index: decoder::load_xrefs(metadata.as_slice()),
+            key_map: decoder::load_key_map(metadata.as_slice()),
             data: metadata,
             cnum_map: RefCell::new(cnum_map),
             cnum: cnum,
index 54e078a16f0a1269dcacd8cf544cc7dfe2421945..b87b5492f0440405151b4545c6990ebce4edaf5f 100644 (file)
@@ -22,6 +22,7 @@
 
 use rustc::dep_graph::DepNode;
 use rustc::hir::map as hir_map;
+use rustc::hir::map::DefKey;
 use rustc::mir::repr::Mir;
 use rustc::mir::mir_map::MirMap;
 use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
@@ -408,6 +409,14 @@ fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId>
         decoder::get_reachable_ids(&cdata)
     }
 
+    fn def_index_for_def_key(&self,
+                             cnum: ast::CrateNum,
+                             def: DefKey)
+                             -> Option<DefIndex> {
+        let cdata = self.get_crate_data(cnum);
+        cdata.key_map.get(&def).cloned()
+    }
+
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
index d3c4c5b02920ab4907c37b2415d76b0ec9e599de..2e1bdf21c9a5ac072a675c9316a75dd66207f0ed 100644 (file)
@@ -21,7 +21,8 @@
 use loader;
 
 use rustc::dep_graph::DepGraph;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::hir::map::DefKey;
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::{ExternCrate};
 use rustc::session::config::PanicStrategy;
@@ -79,6 +80,13 @@ pub struct crate_metadata {
     pub index: index::Index,
     pub xref_index: index::DenseIndex,
 
+    /// For each public item in this crate, we encode a key.  When the
+    /// crate is loaded, we read all the keys and put them in this
+    /// hashmap, which gives the reverse mapping.  This allows us to
+    /// quickly retrace a `DefPath`, which is needed for incremental
+    /// compilation support.
+    pub key_map: FnvHashMap<DefKey, DefIndex>,
+
     /// Flag if this crate is required by an rlib version of this crate, or in
     /// other words whether it was explicitly linked to. An example of a crate
     /// where this is false is when an allocator crate is injected into the
index 5e4c9f39e35f7ecccb0b19af96f6038a3d6637a9..b6f35074b7dc701cf7a8f0d79339311561e84e57 100644 (file)
@@ -25,6 +25,7 @@
 
 use rustc::hir::svh::Svh;
 use rustc::hir::map as hir_map;
+use rustc::hir::map::DefKey;
 use rustc::util::nodemap::FnvHashMap;
 use rustc::hir;
 use rustc::session::config::PanicStrategy;
@@ -95,6 +96,29 @@ pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
     index::DenseIndex::from_buf(index.data, index.start, index.end)
 }
 
+// Go through each item in the metadata and create a map from that
+// item's def-key to the item's DefIndex.
+pub fn load_key_map(data: &[u8]) -> FnvHashMap<DefKey, DefIndex> {
+    let root_doc = rbml::Doc::new(data);
+    let items_doc = reader::get_doc(root_doc, tag_items);
+    let items_data_doc = reader::get_doc(items_doc, tag_items_data);
+    reader::docs(items_data_doc)
+        .filter(|&(tag, _)| tag == tag_items_data_item)
+        .map(|(_, item_doc)| {
+            // load def-key from item
+            let key = item_def_key(item_doc);
+
+            // load def-index from item; we only encode the full def-id,
+            // so just pull out the index
+            let def_id_doc = reader::get_doc(item_doc, tag_def_id);
+            let def_id = untranslated_def_id(def_id_doc);
+            assert!(def_id.is_local()); // local to the crate we are decoding, that is
+
+            (key, def_id.index)
+        })
+        .collect()
+}
+
 #[derive(Clone, Copy, Debug, PartialEq)]
 enum Family {
     ImmStatic,             // c
@@ -193,10 +217,14 @@ fn item_symbol(item: rbml::Doc) -> String {
     reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string()
 }
 
-fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId {
+fn untranslated_def_id(d: rbml::Doc) -> DefId {
     let id = reader::doc_as_u64(d);
     let index = DefIndex::new((id & 0xFFFF_FFFF) as usize);
-    let def_id = DefId { krate: (id >> 32) as u32, index: index };
+    DefId { krate: (id >> 32) as u32, index: index }
+}
+
+fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId {
+    let def_id = untranslated_def_id(d);
     translate_def_id(cdata, def_id)
 }
 
@@ -1750,6 +1778,10 @@ pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 't
 pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey {
     debug!("def_key: id={:?}", id);
     let item_doc = cdata.lookup_item(id);
+    item_def_key(item_doc)
+}
+
+fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
     match reader::maybe_get_doc(item_doc, tag_def_key) {
         Some(def_key_doc) => {
             let mut decoder = reader::Decoder::new(def_key_doc);