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:
parent
6056c5fbed
commit
ab9b844146
@ -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!() }
|
||||
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ use rustc::back::svh::Svh;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::middle::cstore::{CrateStore, validate_crate_name};
|
||||
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
|
||||
use rustc::util::nodemap::FnvHashMap;
|
||||
use rustc::front::map as hir_map;
|
||||
|
||||
@ -38,7 +38,6 @@ use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::errors::FatalError;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::util::small_vector::SmallVector;
|
||||
use rustc_front::intravisit::Visitor;
|
||||
use rustc_front::hir;
|
||||
use log;
|
||||
@ -344,15 +343,13 @@ impl<'a> CrateReader<'a> {
|
||||
|
||||
let cmeta = Rc::new(cstore::crate_metadata {
|
||||
name: name.to_string(),
|
||||
local_path: RefCell::new(SmallVector::zero()),
|
||||
local_def_path: RefCell::new(vec![]),
|
||||
extern_crate: Cell::new(None),
|
||||
index: decoder::load_index(metadata.as_slice()),
|
||||
xref_index: decoder::load_xrefs(metadata.as_slice()),
|
||||
data: metadata,
|
||||
cnum_map: RefCell::new(cnum_map),
|
||||
cnum: cnum,
|
||||
codemap_import_info: RefCell::new(vec![]),
|
||||
span: span,
|
||||
staged_api: staged_api,
|
||||
explicitly_linked: Cell::new(explicitly_linked),
|
||||
});
|
||||
@ -386,8 +383,7 @@ impl<'a> CrateReader<'a> {
|
||||
span: Span,
|
||||
kind: PathKind,
|
||||
explicitly_linked: bool)
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||
cstore::CrateSource) {
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>, cstore::CrateSource) {
|
||||
enum LookupResult {
|
||||
Previous(ast::CrateNum),
|
||||
Loaded(loader::Library),
|
||||
@ -444,23 +440,54 @@ impl<'a> CrateReader<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_extern_crate(&mut self,
|
||||
cnum: ast::CrateNum,
|
||||
mut extern_crate: ExternCrate)
|
||||
{
|
||||
let cmeta = self.cstore.get_crate_data(cnum);
|
||||
let old_extern_crate = cmeta.extern_crate.get();
|
||||
|
||||
// Prefer:
|
||||
// - something over nothing (tuple.0);
|
||||
// - direct extern crate to indirect (tuple.1);
|
||||
// - shorter paths to longer (tuple.2).
|
||||
let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
|
||||
let old_rank = match old_extern_crate {
|
||||
None => (false, false, !0),
|
||||
Some(ref c) => (true, c.direct, !c.path_len),
|
||||
};
|
||||
|
||||
if old_rank >= new_rank {
|
||||
return; // no change needed
|
||||
}
|
||||
|
||||
cmeta.extern_crate.set(Some(extern_crate));
|
||||
|
||||
// Propagate the extern crate info to dependencies.
|
||||
extern_crate.direct = false;
|
||||
for &dep_cnum in cmeta.cnum_map.borrow().values() {
|
||||
self.update_extern_crate(dep_cnum, extern_crate);
|
||||
}
|
||||
}
|
||||
|
||||
// Go through the crate metadata and load any crates that it references
|
||||
fn resolve_crate_deps(&mut self,
|
||||
root: &Option<CratePaths>,
|
||||
cdata: &[u8], span : Span)
|
||||
-> cstore::cnum_map {
|
||||
cdata: &[u8],
|
||||
span : Span)
|
||||
-> cstore::cnum_map {
|
||||
debug!("resolving deps of external crate");
|
||||
// The map from crate numbers in the crate we're resolving to local crate
|
||||
// numbers
|
||||
decoder::get_crate_deps(cdata).iter().map(|dep| {
|
||||
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
|
||||
let (local_cnum, _, _) = self.resolve_crate(root,
|
||||
&dep.name,
|
||||
&dep.name,
|
||||
Some(&dep.hash),
|
||||
span,
|
||||
PathKind::Dependency,
|
||||
dep.explicitly_linked);
|
||||
&dep.name,
|
||||
&dep.name,
|
||||
Some(&dep.hash),
|
||||
span,
|
||||
PathKind::Dependency,
|
||||
dep.explicitly_linked);
|
||||
(dep.cnum, local_cnum)
|
||||
}).collect()
|
||||
}
|
||||
@ -802,19 +829,24 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
|
||||
|
||||
match self.creader.extract_crate_info_hir(i) {
|
||||
Some(info) => {
|
||||
let (cnum, cmeta, _) = self.creader.resolve_crate(&None,
|
||||
&info.ident,
|
||||
&info.name,
|
||||
None,
|
||||
i.span,
|
||||
PathKind::Crate,
|
||||
true);
|
||||
let (cnum, _, _) = self.creader.resolve_crate(&None,
|
||||
&info.ident,
|
||||
&info.name,
|
||||
None,
|
||||
i.span,
|
||||
PathKind::Crate,
|
||||
true);
|
||||
let def_id = self.ast_map.local_def_id(i.id);
|
||||
let def_path = self.ast_map.def_path(def_id);
|
||||
cmeta.update_local_def_path(def_path);
|
||||
self.ast_map.with_path(i.id, |path| {
|
||||
cmeta.update_local_path(path)
|
||||
});
|
||||
|
||||
let len = self.ast_map.def_path(def_id).data.len();
|
||||
|
||||
self.creader.update_extern_crate(cnum,
|
||||
ExternCrate {
|
||||
def_id: def_id,
|
||||
span: i.span,
|
||||
direct: true,
|
||||
path_len: len,
|
||||
});
|
||||
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
|
||||
}
|
||||
None => ()
|
||||
|
@ -13,7 +13,7 @@ use decoder;
|
||||
use encoder;
|
||||
use loader;
|
||||
|
||||
use middle::cstore::{CrateStore, CrateSource, ChildItem, FoundAst};
|
||||
use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst};
|
||||
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
|
||||
use middle::def;
|
||||
use middle::lang_items;
|
||||
@ -128,16 +128,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
decoder::get_method_arg_names(&cdata, did.index)
|
||||
}
|
||||
|
||||
fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem> {
|
||||
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> {
|
||||
let cdata = self.get_crate_data(def.krate);
|
||||
let path = decoder::get_item_path(&cdata, def.index);
|
||||
|
||||
cdata.with_local_path(|cpath| {
|
||||
let mut r = Vec::with_capacity(cpath.len() + path.len());
|
||||
r.extend_from_slice(cpath);
|
||||
r.extend_from_slice(&path);
|
||||
r
|
||||
})
|
||||
decoder::get_item_path(&cdata, def.index)
|
||||
}
|
||||
|
||||
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> {
|
||||
@ -344,6 +337,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
token::intern_and_get_ident(&self.get_crate_data(cnum).name())
|
||||
}
|
||||
|
||||
fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate>
|
||||
{
|
||||
self.get_crate_data(cnum).extern_crate.get()
|
||||
}
|
||||
|
||||
fn crate_hash(&self, cnum: ast::CrateNum) -> Svh
|
||||
{
|
||||
let cdata = self.get_crate_data(cnum);
|
||||
@ -383,12 +381,17 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
decoder::get_reachable_ids(&cdata)
|
||||
}
|
||||
|
||||
fn def_path(&self, def: DefId) -> hir_map::DefPath
|
||||
{
|
||||
/// 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.
|
||||
fn def_key(&self, def: DefId) -> hir_map::DefKey {
|
||||
let cdata = self.get_crate_data(def.krate);
|
||||
let path = decoder::def_path(&cdata, def.index);
|
||||
let local_path = cdata.local_def_path();
|
||||
local_path.into_iter().chain(path).collect()
|
||||
decoder::def_key(&cdata, def.index)
|
||||
}
|
||||
|
||||
fn relative_def_path(&self, def: DefId) -> hir_map::DefPath {
|
||||
let cdata = self.get_crate_data(def.krate);
|
||||
decoder::def_path(&cdata, def.index)
|
||||
}
|
||||
|
||||
fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> {
|
||||
|
@ -21,7 +21,7 @@ use index;
|
||||
use loader;
|
||||
|
||||
use rustc::back::svh::Svh;
|
||||
use rustc::front::map as ast_map;
|
||||
use rustc::middle::cstore::{ExternCrate};
|
||||
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
||||
use std::cell::{RefCell, Ref, Cell};
|
||||
@ -31,9 +31,7 @@ use flate::Bytes;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::codemap;
|
||||
use syntax::parse::token;
|
||||
use syntax::parse::token::IdentInterner;
|
||||
use syntax::util::small_vector::SmallVector;
|
||||
|
||||
pub use middle::cstore::{NativeLibraryKind, LinkagePreference};
|
||||
pub use middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
|
||||
@ -63,13 +61,16 @@ pub struct ImportedFileMap {
|
||||
|
||||
pub struct crate_metadata {
|
||||
pub name: String,
|
||||
pub local_path: RefCell<SmallVector<ast_map::PathElem>>,
|
||||
pub local_def_path: RefCell<ast_map::DefPath>,
|
||||
|
||||
/// Information about the extern crate that caused this crate to
|
||||
/// be loaded. If this is `None`, then the crate was injected
|
||||
/// (e.g., by the allocator)
|
||||
pub extern_crate: Cell<Option<ExternCrate>>,
|
||||
|
||||
pub data: MetadataBlob,
|
||||
pub cnum_map: RefCell<cnum_map>,
|
||||
pub cnum: ast::CrateNum,
|
||||
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
||||
pub span: codemap::Span,
|
||||
pub staged_api: bool,
|
||||
|
||||
pub index: index::Index,
|
||||
@ -268,50 +269,6 @@ impl crate_metadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_local_path<T, F>(&self, f: F) -> T
|
||||
where F: Fn(&[ast_map::PathElem]) -> T
|
||||
{
|
||||
let cpath = self.local_path.borrow();
|
||||
if cpath.is_empty() {
|
||||
let name = ast_map::PathMod(token::intern(&self.name));
|
||||
f(&[name])
|
||||
} else {
|
||||
f(cpath.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_local_path<'a, 'b>(&self, candidate: ast_map::PathElems<'a, 'b>) {
|
||||
let mut cpath = self.local_path.borrow_mut();
|
||||
let cap = cpath.len();
|
||||
match cap {
|
||||
0 => *cpath = candidate.collect(),
|
||||
1 => (),
|
||||
_ => {
|
||||
let candidate: SmallVector<_> = candidate.collect();
|
||||
if candidate.len() < cap {
|
||||
*cpath = candidate;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_def_path(&self) -> ast_map::DefPath {
|
||||
let local_def_path = self.local_def_path.borrow();
|
||||
if local_def_path.is_empty() {
|
||||
let name = ast_map::DefPathData::DetachedCrate(token::intern(&self.name));
|
||||
vec![ast_map::DisambiguatedDefPathData { data: name, disambiguator: 0 }]
|
||||
} else {
|
||||
local_def_path.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_local_def_path(&self, candidate: ast_map::DefPath) {
|
||||
let mut local_def_path = self.local_def_path.borrow_mut();
|
||||
if local_def_path.is_empty() || candidate.len() < local_def_path.len() {
|
||||
*local_def_path = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_allocator(&self) -> bool {
|
||||
let attrs = decoder::get_crate_attributes(self.data());
|
||||
attr::contains_name(&attrs, "allocator")
|
||||
|
@ -1763,7 +1763,9 @@ pub fn closure_ty<'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: &TyCtxt<'tcx>)
|
||||
.parse_closure_ty()
|
||||
}
|
||||
|
||||
fn def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
|
||||
pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey {
|
||||
debug!("def_key: id={:?}", id);
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
match reader::maybe_get_doc(item_doc, tag_def_key) {
|
||||
Some(def_key_doc) => {
|
||||
let mut decoder = reader::Decoder::new(def_key_doc);
|
||||
|
Loading…
Reference in New Issue
Block a user