Skip to content

Commit

Permalink
allow retracing paths across crates
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikomatsakis committed May 18, 2016
1 parent 303fdc1 commit b01919a
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 44 deletions.
37 changes: 6 additions & 31 deletions src/librustc/hir/map/definitions.rs
Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 3 additions & 4 deletions src/librustc/hir/map/mod.rs
Expand Up @@ -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, };
Expand Down Expand Up @@ -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 {
Expand Down
17 changes: 14 additions & 3 deletions src/librustc/middle/cstore.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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>;
Expand Down Expand Up @@ -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>
Expand Down
48 changes: 46 additions & 2 deletions src/librustc/ty/context.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_incremental/persist/directory.rs
Expand Up @@ -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 }
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_metadata/creader.rs
Expand Up @@ -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,
Expand Down
9 changes: 9 additions & 0 deletions src/librustc_metadata/csearch.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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.
Expand Down
10 changes: 9 additions & 1 deletion src/librustc_metadata/cstore.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
36 changes: 34 additions & 2 deletions src/librustc_metadata/decoder.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit b01919a

Please sign in to comment.