Skip to content

Commit 8500e5b

Browse files
committed
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.
1 parent ba6d406 commit 8500e5b

File tree

6 files changed

+141
-99
lines changed

6 files changed

+141
-99
lines changed

src/librustc/middle/cstore.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,27 @@ pub enum FoundAst<'ast> {
127127
NotFound,
128128
}
129129

130+
#[derive(Copy, Clone, Debug)]
131+
pub struct ExternCrate {
132+
/// def_id of an `extern crate` in the current crate that caused
133+
/// this crate to be loaded; note that there could be multiple
134+
/// such ids
135+
pub def_id: DefId,
136+
137+
/// span of the extern crate that caused this to be loaded
138+
pub span: Span,
139+
140+
/// If true, then this crate is the crate named by the extern
141+
/// crate referenced above. If false, then this crate is a dep
142+
/// of the crate.
143+
pub direct: bool,
144+
145+
/// Number of links to reach the extern crate `def_id`
146+
/// declaration; used to select the extern crate with the shortest
147+
/// path
148+
pub path_len: usize,
149+
}
150+
130151
/// A store of Rust crates, through with their metadata
131152
/// can be accessed.
132153
///
@@ -147,7 +168,7 @@ pub trait CrateStore<'tcx> : Any {
147168
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
148169
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
149170
-> ty::TypeScheme<'tcx>;
150-
fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
171+
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
151172
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
152173
fn item_name(&self, def: DefId) -> ast::Name;
153174
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
@@ -203,6 +224,7 @@ pub trait CrateStore<'tcx> : Any {
203224
fn is_staged_api(&self, cnum: ast::CrateNum) -> bool;
204225
fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool;
205226
fn is_allocator(&self, cnum: ast::CrateNum) -> bool;
227+
fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate>;
206228
fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>;
207229
/// The name of the crate as it is referred to in source code of the current
208230
/// crate.
@@ -218,7 +240,8 @@ pub trait CrateStore<'tcx> : Any {
218240
fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId>;
219241

220242
// resolve
221-
fn def_path(&self, def: DefId) -> hir_map::DefPath;
243+
fn def_key(&self, def: DefId) -> hir_map::DefKey;
244+
fn relative_def_path(&self, def: DefId) -> hir_map::DefPath;
222245
fn variant_kind(&self, def_id: DefId) -> Option<VariantKind>;
223246
fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>;
224247
fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>;
@@ -323,7 +346,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
323346
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { unimplemented!() }
324347
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
325348
-> ty::TypeScheme<'tcx> { unimplemented!() }
326-
fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
349+
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
327350
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
328351
fn item_name(&self, def: DefId) -> ast::Name { unimplemented!() }
329352
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
@@ -386,6 +409,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
386409
fn is_staged_api(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
387410
fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
388411
fn is_allocator(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
412+
fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate> { unimplemented!() }
389413
fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>
390414
{ unimplemented!() }
391415
fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
@@ -404,7 +428,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
404428
fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { unimplemented!() }
405429

406430
// resolve
407-
fn def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
431+
fn def_key(&self, def: DefId) -> hir_map::DefKey { unimplemented!() }
432+
fn relative_def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
408433
fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { unimplemented!() }
409434
fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
410435
{ unimplemented!() }

src/librustc/middle/ty/mod.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -2222,11 +2222,14 @@ impl<'tcx> TyCtxt<'tcx> {
22222222
self.with_path(id, |path| ast_map::path_to_string(path))
22232223
}
22242224

2225+
/// Returns the `DefPath` of an item. Note that if `id` is not
2226+
/// local to this crate -- or is inlined into this crate -- the
2227+
/// result will be a non-local `DefPath`.
22252228
pub fn def_path(&self, id: DefId) -> ast_map::DefPath {
22262229
if id.is_local() {
22272230
self.map.def_path(id)
22282231
} else {
2229-
self.sess.cstore.def_path(id)
2232+
self.sess.cstore.relative_def_path(id)
22302233
}
22312234
}
22322235

@@ -2236,7 +2239,27 @@ impl<'tcx> TyCtxt<'tcx> {
22362239
if let Some(id) = self.map.as_local_node_id(id) {
22372240
self.map.with_path(id, f)
22382241
} else {
2239-
f(self.sess.cstore.item_path(id).iter().cloned().chain(LinkedPath::empty()))
2242+
let mut path: Vec<_>;
2243+
if let Some(extern_crate) = self.sess.cstore.extern_crate(id.krate) {
2244+
if !extern_crate.direct {
2245+
// this comes from some crate that we don't have a direct
2246+
// path to; we'll settle for just prepending the name of
2247+
// the crate.
2248+
path = self.sess.cstore.extern_item_path(id)
2249+
} else {
2250+
// start with the path to the extern crate, then
2251+
// add the relative path to the actual item
2252+
fn collector(elems: ast_map::PathElems) -> Vec<ast_map::PathElem> {
2253+
elems.collect()
2254+
}
2255+
path = self.with_path(extern_crate.def_id, collector);
2256+
path.extend(self.sess.cstore.relative_item_path(id));
2257+
}
2258+
} else {
2259+
// if this was injected, just make a path with name of crate
2260+
path = self.sess.cstore.extern_item_path(id);
2261+
}
2262+
f(path.iter().cloned().chain(LinkedPath::empty()))
22402263
}
22412264
}
22422265

src/librustc_metadata/creader.rs

+59-27
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc::back::svh::Svh;
2121
use rustc::dep_graph::DepNode;
2222
use rustc::session::{config, Session};
2323
use rustc::session::search_paths::PathKind;
24-
use rustc::middle::cstore::{CrateStore, validate_crate_name};
24+
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
2525
use rustc::util::nodemap::FnvHashMap;
2626
use rustc::front::map as hir_map;
2727

@@ -38,7 +38,6 @@ use syntax::attr;
3838
use syntax::attr::AttrMetaMethods;
3939
use syntax::errors::FatalError;
4040
use syntax::parse::token::InternedString;
41-
use syntax::util::small_vector::SmallVector;
4241
use rustc_front::intravisit::Visitor;
4342
use rustc_front::hir;
4443
use log;
@@ -344,15 +343,13 @@ impl<'a> CrateReader<'a> {
344343

345344
let cmeta = Rc::new(cstore::crate_metadata {
346345
name: name.to_string(),
347-
local_path: RefCell::new(SmallVector::zero()),
348-
local_def_path: RefCell::new(vec![]),
346+
extern_crate: Cell::new(None),
349347
index: decoder::load_index(metadata.as_slice()),
350348
xref_index: decoder::load_xrefs(metadata.as_slice()),
351349
data: metadata,
352350
cnum_map: RefCell::new(cnum_map),
353351
cnum: cnum,
354352
codemap_import_info: RefCell::new(vec![]),
355-
span: span,
356353
staged_api: staged_api,
357354
explicitly_linked: Cell::new(explicitly_linked),
358355
});
@@ -386,8 +383,7 @@ impl<'a> CrateReader<'a> {
386383
span: Span,
387384
kind: PathKind,
388385
explicitly_linked: bool)
389-
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
390-
cstore::CrateSource) {
386+
-> (ast::CrateNum, Rc<cstore::crate_metadata>, cstore::CrateSource) {
391387
enum LookupResult {
392388
Previous(ast::CrateNum),
393389
Loaded(loader::Library),
@@ -444,23 +440,54 @@ impl<'a> CrateReader<'a> {
444440
}
445441
}
446442

443+
fn update_extern_crate(&mut self,
444+
cnum: ast::CrateNum,
445+
mut extern_crate: ExternCrate)
446+
{
447+
let cmeta = self.cstore.get_crate_data(cnum);
448+
let old_extern_crate = cmeta.extern_crate.get();
449+
450+
// Prefer:
451+
// - something over nothing (tuple.0);
452+
// - direct extern crate to indirect (tuple.1);
453+
// - shorter paths to longer (tuple.2).
454+
let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
455+
let old_rank = match old_extern_crate {
456+
None => (false, false, !0),
457+
Some(ref c) => (true, c.direct, !c.path_len),
458+
};
459+
460+
if old_rank >= new_rank {
461+
return; // no change needed
462+
}
463+
464+
cmeta.extern_crate.set(Some(extern_crate));
465+
466+
// Propagate the extern crate info to dependencies.
467+
extern_crate.direct = false;
468+
for &dep_cnum in cmeta.cnum_map.borrow().values() {
469+
self.update_extern_crate(dep_cnum, extern_crate);
470+
}
471+
}
472+
447473
// Go through the crate metadata and load any crates that it references
448474
fn resolve_crate_deps(&mut self,
449475
root: &Option<CratePaths>,
450-
cdata: &[u8], span : Span)
451-
-> cstore::cnum_map {
476+
cdata: &[u8],
477+
span : Span)
478+
-> cstore::cnum_map {
452479
debug!("resolving deps of external crate");
453480
// The map from crate numbers in the crate we're resolving to local crate
454481
// numbers
455482
decoder::get_crate_deps(cdata).iter().map(|dep| {
456483
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
457484
let (local_cnum, _, _) = self.resolve_crate(root,
458-
&dep.name,
459-
&dep.name,
460-
Some(&dep.hash),
461-
span,
462-
PathKind::Dependency,
463-
dep.explicitly_linked);
485+
&dep.name,
486+
&dep.name,
487+
Some(&dep.hash),
488+
span,
489+
PathKind::Dependency,
490+
dep.explicitly_linked);
464491
(dep.cnum, local_cnum)
465492
}).collect()
466493
}
@@ -802,19 +829,24 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
802829

803830
match self.creader.extract_crate_info_hir(i) {
804831
Some(info) => {
805-
let (cnum, cmeta, _) = self.creader.resolve_crate(&None,
806-
&info.ident,
807-
&info.name,
808-
None,
809-
i.span,
810-
PathKind::Crate,
811-
true);
832+
let (cnum, _, _) = self.creader.resolve_crate(&None,
833+
&info.ident,
834+
&info.name,
835+
None,
836+
i.span,
837+
PathKind::Crate,
838+
true);
812839
let def_id = self.ast_map.local_def_id(i.id);
813-
let def_path = self.ast_map.def_path(def_id);
814-
cmeta.update_local_def_path(def_path);
815-
self.ast_map.with_path(i.id, |path| {
816-
cmeta.update_local_path(path)
817-
});
840+
841+
let len = self.ast_map.def_path(def_id).data.len();
842+
843+
self.creader.update_extern_crate(cnum,
844+
ExternCrate {
845+
def_id: def_id,
846+
span: i.span,
847+
direct: true,
848+
path_len: len,
849+
});
818850
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
819851
}
820852
None => ()

src/librustc_metadata/csearch.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use decoder;
1313
use encoder;
1414
use loader;
1515

16-
use middle::cstore::{CrateStore, CrateSource, ChildItem, FoundAst};
16+
use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst};
1717
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
1818
use middle::def;
1919
use middle::lang_items;
@@ -128,16 +128,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
128128
decoder::get_method_arg_names(&cdata, did.index)
129129
}
130130

131-
fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem> {
131+
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> {
132132
let cdata = self.get_crate_data(def.krate);
133-
let path = decoder::get_item_path(&cdata, def.index);
134-
135-
cdata.with_local_path(|cpath| {
136-
let mut r = Vec::with_capacity(cpath.len() + path.len());
137-
r.extend_from_slice(cpath);
138-
r.extend_from_slice(&path);
139-
r
140-
})
133+
decoder::get_item_path(&cdata, def.index)
141134
}
142135

143136
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> {
@@ -344,6 +337,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
344337
token::intern_and_get_ident(&self.get_crate_data(cnum).name())
345338
}
346339

340+
fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate>
341+
{
342+
self.get_crate_data(cnum).extern_crate.get()
343+
}
344+
347345
fn crate_hash(&self, cnum: ast::CrateNum) -> Svh
348346
{
349347
let cdata = self.get_crate_data(cnum);
@@ -383,12 +381,17 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
383381
decoder::get_reachable_ids(&cdata)
384382
}
385383

386-
fn def_path(&self, def: DefId) -> hir_map::DefPath
387-
{
384+
/// Returns the `DefKey` for a given `DefId`. This indicates the
385+
/// parent `DefId` as well as some idea of what kind of data the
386+
/// `DefId` refers to.
387+
fn def_key(&self, def: DefId) -> hir_map::DefKey {
388+
let cdata = self.get_crate_data(def.krate);
389+
decoder::def_key(&cdata, def.index)
390+
}
391+
392+
fn relative_def_path(&self, def: DefId) -> hir_map::DefPath {
388393
let cdata = self.get_crate_data(def.krate);
389-
let path = decoder::def_path(&cdata, def.index);
390-
let local_path = cdata.local_def_path();
391-
local_path.into_iter().chain(path).collect()
394+
decoder::def_path(&cdata, def.index)
392395
}
393396

394397
fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> {

0 commit comments

Comments
 (0)