diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-05-06 14:52:57 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-05-18 10:11:36 -0400 |
| commit | b01919a1443615f2ee78f91515e8f01dc2591177 (patch) | |
| tree | 3c7f7f49d4e53e57517a88c0466e203a37b39b0a | |
| parent | 303fdc17f6bb842668e0fdd1e1a2c16841ae7373 (diff) | |
| download | rust-b01919a1443615f2ee78f91515e8f01dc2591177.tar.gz rust-b01919a1443615f2ee78f91515e8f01dc2591177.zip | |
allow retracing paths across crates
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.
| -rw-r--r-- | src/librustc/hir/map/definitions.rs | 37 | ||||
| -rw-r--r-- | src/librustc/hir/map/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/middle/cstore.rs | 17 | ||||
| -rw-r--r-- | src/librustc/ty/context.rs | 48 | ||||
| -rw-r--r-- | src/librustc_incremental/persist/directory.rs | 2 | ||||
| -rw-r--r-- | src/librustc_metadata/creader.rs | 1 | ||||
| -rw-r--r-- | src/librustc_metadata/csearch.rs | 9 | ||||
| -rw-r--r-- | src/librustc_metadata/cstore.rs | 10 | ||||
| -rw-r--r-- | src/librustc_metadata/decoder.rs | 36 |
9 files changed, 123 insertions, 44 deletions
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 358301ab404..457511cdbc3 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -82,8 +82,10 @@ impl DefPath { 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 @@ impl Definitions { 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 @@ impl Definitions { } } - 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, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e3976482dca..2f310806a74 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -19,7 +19,7 @@ use dep_graph::{DepGraph, DepNode}; 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 @@ impl<'ast> Map<'ast> { 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 { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 17c6442c019..e5a8c1d1b4e 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -22,12 +22,13 @@ // 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 @@ pub trait CrateStore<'tcx> { 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 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { -> 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> diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 39fe744c67d..ea169b1d3b6 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -11,13 +11,14 @@ //! 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + /// 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> diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs index e256b7cf7d0..07753158753 100644 --- a/src/librustc_incremental/persist/directory.rs +++ b/src/librustc_incremental/persist/directory.rs @@ -41,7 +41,7 @@ impl 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 } } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 63c6af704bb..0eacc0907bc 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -319,6 +319,7 @@ impl<'a> CrateReader<'a> { 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, diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 54e078a16f0..b87b5492f04 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -22,6 +22,7 @@ use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; 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 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { 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. diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index d3c4c5b0292..2e1bdf21c9a 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -21,7 +21,8 @@ use index; 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 diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5e4c9f39e35..b6f35074b7d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -25,6 +25,7 @@ use tydecode::TyDecoder; 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); |
