track the extern-crate def-id rather than path

We used to track, for each crate, a path that led to the extern-crate
that imported it. Instead of that, track the def-id of the extern crate,
along with a bit more information, and derive the path on the fly.
This commit is contained in:
Niko Matsakis 2016-03-16 05:50:38 -04:00
parent 6056c5fbed
commit ab9b844146
6 changed files with 141 additions and 99 deletions

View file

@ -127,6 +127,27 @@ pub enum FoundAst<'ast> {
NotFound,
}
#[derive(Copy, Clone, Debug)]
pub struct ExternCrate {
/// def_id of an `extern crate` in the current crate that caused
/// this crate to be loaded; note that there could be multiple
/// such ids
pub def_id: DefId,
/// span of the extern crate that caused this to be loaded
pub span: Span,
/// If true, then this crate is the crate named by the extern
/// crate referenced above. If false, then this crate is a dep
/// of the crate.
pub direct: bool,
/// Number of links to reach the extern crate `def_id`
/// declaration; used to select the extern crate with the shortest
/// path
pub path_len: usize,
}
/// A store of Rust crates, through with their metadata
/// can be accessed.
///
@ -147,7 +168,7 @@ pub trait CrateStore<'tcx> : Any {
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::TypeScheme<'tcx>;
fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
fn item_name(&self, def: DefId) -> ast::Name;
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
@ -203,6 +224,7 @@ pub trait CrateStore<'tcx> : Any {
fn is_staged_api(&self, cnum: ast::CrateNum) -> bool;
fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool;
fn is_allocator(&self, cnum: ast::CrateNum) -> bool;
fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate>;
fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>;
/// The name of the crate as it is referred to in source code of the current
/// crate.
@ -218,7 +240,8 @@ pub trait CrateStore<'tcx> : Any {
fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId>;
// resolve
fn def_path(&self, def: DefId) -> hir_map::DefPath;
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>;
fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>;
fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>;
@ -323,7 +346,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { unimplemented!() }
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-> ty::TypeScheme<'tcx> { unimplemented!() }
fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
fn item_name(&self, def: DefId) -> ast::Name { unimplemented!() }
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
@ -386,6 +409,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn is_staged_api(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
fn is_allocator(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate> { unimplemented!() }
fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>
{ unimplemented!() }
fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
@ -404,7 +428,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { unimplemented!() }
// resolve
fn def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
fn def_key(&self, def: DefId) -> hir_map::DefKey { unimplemented!() }
fn relative_def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { unimplemented!() }
fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
{ unimplemented!() }

View file

@ -2222,11 +2222,14 @@ impl<'tcx> TyCtxt<'tcx> {
self.with_path(id, |path| ast_map::path_to_string(path))
}
/// Returns the `DefPath` of an item. Note that if `id` is not
/// local to this crate -- or is inlined into this crate -- the
/// result will be a non-local `DefPath`.
pub fn def_path(&self, id: DefId) -> ast_map::DefPath {
if id.is_local() {
self.map.def_path(id)
} else {
self.sess.cstore.def_path(id)
self.sess.cstore.relative_def_path(id)
}
}
@ -2236,7 +2239,27 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = self.map.as_local_node_id(id) {
self.map.with_path(id, f)
} else {
f(self.sess.cstore.item_path(id).iter().cloned().chain(LinkedPath::empty()))
let mut path: Vec<_>;
if let Some(extern_crate) = self.sess.cstore.extern_crate(id.krate) {
if !extern_crate.direct {
// this comes from some crate that we don't have a direct
// path to; we'll settle for just prepending the name of
// the crate.
path = self.sess.cstore.extern_item_path(id)
} else {
// start with the path to the extern crate, then
// add the relative path to the actual item
fn collector(elems: ast_map::PathElems) -> Vec<ast_map::PathElem> {
elems.collect()
}
path = self.with_path(extern_crate.def_id, collector);
path.extend(self.sess.cstore.relative_item_path(id));
}
} else {
// if this was injected, just make a path with name of crate
path = self.sess.cstore.extern_item_path(id);
}
f(path.iter().cloned().chain(LinkedPath::empty()))
}
}