Skip to content

Commit 0c6f067

Browse files
committed
Add method visible_item_path to CStore
1 parent d5a91e6 commit 0c6f067

File tree

4 files changed

+111
-6
lines changed

4 files changed

+111
-6
lines changed

src/librustc/middle/cstore.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use mir::repr::Mir;
3232
use mir::mir_map::MirMap;
3333
use session::Session;
3434
use session::search_paths::PathKind;
35-
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
35+
use util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
3636
use std::any::Any;
3737
use std::cell::RefCell;
3838
use std::rc::Rc;
@@ -169,6 +169,7 @@ pub trait CrateStore<'tcx> : Any {
169169
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
170170
-> ty::TypeScheme<'tcx>;
171171
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
172+
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
172173
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
173174
fn item_name(&self, def: DefId) -> ast::Name;
174175
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
@@ -347,6 +348,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
347348
fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
348349
-> ty::TypeScheme<'tcx> { unimplemented!() }
349350
fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
351+
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
352+
unimplemented!()
353+
}
350354
fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
351355
fn item_name(&self, def: DefId) -> ast::Name { unimplemented!() }
352356
fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)

src/librustc/ty/item_path.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use front::map::DefPathData;
1212
use middle::cstore::LOCAL_CRATE;
13-
use middle::def_id::DefId;
13+
use middle::def_id::{DefId, CRATE_DEF_INDEX};
1414
use ty::{self, Ty, TyCtxt};
1515
use syntax::ast;
1616

@@ -75,9 +75,51 @@ impl<'tcx> TyCtxt<'tcx> {
7575
}
7676
}
7777

78+
/// If possible, this pushes a global path resolving to `external_def_id` that is visible
79+
/// from at least one local module and returns true. If the crate defining `external_def_id` is
80+
/// declared with an `extern crate`, the path is guarenteed to use the `extern crate`.
81+
pub fn try_push_visible_item_path<T>(&self, buffer: &mut T, external_def_id: DefId) -> bool
82+
where T: ItemPathBuffer
83+
{
84+
let visible_parent_map = self.sess.cstore.visible_parent_map();
85+
86+
let (mut cur_def, mut cur_path) = (external_def_id, Vec::<ast::Name>::new());
87+
loop {
88+
// If `cur_def` is a direct or injected extern crate, push the path to the crate
89+
// followed by the path to the item within the crate and return.
90+
if cur_def.index == CRATE_DEF_INDEX {
91+
match self.sess.cstore.extern_crate(cur_def.krate) {
92+
Some(extern_crate) if extern_crate.direct => {
93+
self.push_item_path(buffer, extern_crate.def_id);
94+
cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
95+
return true;
96+
}
97+
None => {
98+
buffer.push(&self.crate_name(cur_def.krate));
99+
cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
100+
return true;
101+
}
102+
_ => {},
103+
}
104+
}
105+
106+
cur_path.push(self.sess.cstore.item_name(cur_def));
107+
match visible_parent_map.get(&cur_def) {
108+
Some(&def) => cur_def = def,
109+
None => return false,
110+
};
111+
}
112+
}
113+
78114
pub fn push_item_path<T>(&self, buffer: &mut T, def_id: DefId)
79115
where T: ItemPathBuffer
80116
{
117+
match *buffer.root_mode() {
118+
RootMode::Local if !def_id.is_local() =>
119+
if self.try_push_visible_item_path(buffer, def_id) { return },
120+
_ => {}
121+
}
122+
81123
let key = self.def_key(def_id);
82124
match key.disambiguated_data.data {
83125
DefPathData::CrateRoot => {

src/librustc_metadata/csearch.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ use decoder;
1313
use encoder;
1414
use loader;
1515

16-
use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst};
16+
use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst, DefLike};
1717
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
1818
use middle::def;
1919
use middle::lang_items;
2020
use rustc::ty::{self, Ty, TyCtxt, VariantKind};
21-
use middle::def_id::{DefId, DefIndex};
21+
use middle::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
2222

2323
use rustc::front::map as hir_map;
2424
use rustc::mir::repr::Mir;
2525
use rustc::mir::mir_map::MirMap;
26-
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
26+
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
2727

2828
use std::cell::RefCell;
2929
use std::rc::Rc;
@@ -544,4 +544,60 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
544544
{
545545
encoder::metadata_encoding_version
546546
}
547+
548+
/// Returns a map from a sufficiently visible external item (i.e. an external item that is
549+
/// visible from at least one local module) to a sufficiently visible parent (considering
550+
/// modules that re-export the external item to be parents).
551+
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
552+
let mut visible_parent_map = self.visible_parent_map.borrow_mut();
553+
if !visible_parent_map.is_empty() { return visible_parent_map; }
554+
555+
use rustc_front::hir;
556+
use rustc::middle::cstore::{CrateStore, ChildItem};
557+
use std::collections::vec_deque::VecDeque;
558+
use std::collections::hash_map::Entry;
559+
for cnum in 1 .. self.next_crate_num() {
560+
let cdata = self.get_crate_data(cnum);
561+
562+
match cdata.extern_crate.get() {
563+
// Ignore crates without a corresponding local `extern crate` item.
564+
Some(extern_crate) if !extern_crate.direct => continue,
565+
_ => {},
566+
}
567+
568+
let mut bfs_queue = &mut VecDeque::new();
569+
let mut add_child = |bfs_queue: &mut VecDeque<_>, child: ChildItem, parent: DefId| {
570+
let child = match child.def {
571+
DefLike::DlDef(def) if child.vis == hir::Public => def.def_id(),
572+
_ => return,
573+
};
574+
575+
match visible_parent_map.entry(child) {
576+
Entry::Occupied(mut entry) => {
577+
// If `child` is defined in crate `cnum`, ensure
578+
// that it is mapped to a parent in `cnum`.
579+
if child.krate == cnum && entry.get().krate != cnum {
580+
entry.insert(parent);
581+
}
582+
}
583+
Entry::Vacant(entry) => {
584+
entry.insert(parent);
585+
bfs_queue.push_back(child);
586+
}
587+
}
588+
};
589+
590+
let croot = DefId { krate: cnum, index: CRATE_DEF_INDEX };
591+
for child in self.crate_top_level_items(cnum) {
592+
add_child(bfs_queue, child, croot);
593+
}
594+
while let Some(def) = bfs_queue.pop_front() {
595+
for child in self.item_children(def) {
596+
add_child(bfs_queue, child, def);
597+
}
598+
}
599+
}
600+
601+
visible_parent_map
602+
}
547603
}

src/librustc_metadata/cstore.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use loader;
2222

2323
use rustc::back::svh::Svh;
2424
use rustc::middle::cstore::{ExternCrate};
25-
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
25+
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
26+
use rustc::middle::def_id::DefId;
2627

2728
use std::cell::{RefCell, Ref, Cell};
2829
use std::rc::Rc;
@@ -92,6 +93,7 @@ pub struct CStore {
9293
used_link_args: RefCell<Vec<String>>,
9394
statically_included_foreign_items: RefCell<NodeSet>,
9495
pub intr: Rc<IdentInterner>,
96+
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
9597
}
9698

9799
impl CStore {
@@ -104,6 +106,7 @@ impl CStore {
104106
used_link_args: RefCell::new(Vec::new()),
105107
intr: intr,
106108
statically_included_foreign_items: RefCell::new(NodeSet()),
109+
visible_parent_map: RefCell::new(FnvHashMap()),
107110
}
108111
}
109112

0 commit comments

Comments
 (0)