librustc: Remove each_path.

This does not implement lazy symbol resolution yet.
This commit is contained in:
Patrick Walton 2013-08-21 17:26:33 -07:00
parent 1ad2239f62
commit 1bbb1e06f1
3 changed files with 286 additions and 258 deletions

View File

@ -49,16 +49,34 @@ pub fn each_lang_item(cstore: @mut cstore::CStore,
decoder::each_lang_item(crate_data, f)
}
/// Iterates over all the paths in the given crate.
pub fn each_path(cstore: @mut cstore::CStore,
cnum: ast::CrateNum,
f: &fn(&str, decoder::def_like, ast::visibility) -> bool)
-> bool {
/// Iterates over each child of the given item.
pub fn each_child_of_item(cstore: @mut cstore::CStore,
def_id: ast::def_id,
callback: &fn(decoder::def_like, ast::ident)) {
let crate_data = cstore::get_crate_data(cstore, def_id.crate);
let get_crate_data: decoder::GetCrateDataCb = |cnum| {
cstore::get_crate_data(cstore, cnum)
};
decoder::each_child_of_item(cstore.intr,
crate_data,
def_id.node,
get_crate_data,
callback)
}
/// Iterates over each top-level crate item.
pub fn each_top_level_item_of_crate(cstore: @mut cstore::CStore,
cnum: ast::CrateNum,
callback: &fn(decoder::def_like,
ast::ident)) {
let crate_data = cstore::get_crate_data(cstore, cnum);
let get_crate_data: decoder::GetCrateDataCb = |cnum| {
cstore::get_crate_data(cstore, cnum)
};
decoder::each_path(cstore.intr, crate_data, get_crate_data, f)
decoder::each_top_level_item_of_crate(cstore.intr,
crate_data,
get_crate_data,
callback)
}
pub fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path {

View File

@ -39,7 +39,7 @@ use syntax::ast_map;
use syntax::attr;
use syntax::parse::token::{ident_interner, special_idents};
use syntax::print::pprust;
use syntax::{ast, ast_util};
use syntax::ast;
use syntax::codemap;
use syntax::parse::token;
@ -702,33 +702,114 @@ impl<'self> EachItemContext<'self> {
}
}
/// Iterates over all the paths in the given crate.
pub fn each_path(intr: @ident_interner,
cdata: cmd,
get_crate_data: GetCrateDataCb,
f: &fn(&str, def_like, ast::visibility) -> bool)
-> bool {
// FIXME #4572: This function needs to be nuked, as it's impossible to
// make fast. It's the source of most of the performance problems when
// compiling small crates.
fn each_child_of_item_or_crate(intr: @ident_interner,
cdata: cmd,
item_doc: ebml::Doc,
get_crate_data: GetCrateDataCb,
callback: &fn(def_like, ast::ident)) {
// Iterate over all children.
let _ = do reader::tagged_docs(item_doc, tag_mod_child) |child_info_doc| {
let child_def_id = reader::with_doc_data(child_info_doc,
parse_def_id);
let child_def_id = translate_def_id(cdata, child_def_id);
// This item may be in yet another crate if it was the child of a
// reexport.
let other_crates_items = if child_def_id.crate == cdata.cnum {
reader::get_doc(reader::Doc(cdata.data), tag_items)
} else {
let crate_data = get_crate_data(child_def_id.crate);
reader::get_doc(reader::Doc(crate_data.data), tag_items)
};
// Get the item.
match maybe_find_item(child_def_id.node, other_crates_items) {
None => {}
Some(child_item_doc) => {
// Hand off the item to the callback.
let child_name = item_name(intr, child_item_doc);
let def_like = item_to_def_like(child_item_doc,
child_def_id,
cdata.cnum);
callback(def_like, child_name);
}
}
true
};
// Iterate over all reexports.
let _ = do each_reexport(item_doc) |reexport_doc| {
let def_id_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let child_def_id = reader::with_doc_data(def_id_doc,
parse_def_id);
let child_def_id = translate_def_id(cdata, child_def_id);
let name_doc = reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
let name = name_doc.as_str_slice();
// This reexport may be in yet another crate.
let other_crates_items = if child_def_id.crate == cdata.cnum {
reader::get_doc(reader::Doc(cdata.data), tag_items)
} else {
let crate_data = get_crate_data(child_def_id.crate);
reader::get_doc(reader::Doc(crate_data.data), tag_items)
};
// Get the item.
match maybe_find_item(child_def_id.node, other_crates_items) {
None => {}
Some(child_item_doc) => {
// Hand off the item to the callback.
let def_like = item_to_def_like(child_item_doc,
child_def_id,
cdata.cnum);
callback(def_like, token::str_to_ident(name));
}
}
true
};
}
/// Iterates over each child of the given item.
pub fn each_child_of_item(intr: @ident_interner,
cdata: cmd,
id: ast::NodeId,
get_crate_data: GetCrateDataCb,
callback: &fn(def_like, ast::ident)) {
// Find the item.
let root_doc = reader::Doc(cdata.data);
let items = reader::get_doc(root_doc, tag_items);
let item_doc = match maybe_find_item(id, items) {
None => return,
Some(item_doc) => item_doc,
};
each_child_of_item_or_crate(intr,
cdata,
item_doc,
get_crate_data,
callback)
}
/// Iterates over all the top-level crate items.
pub fn each_top_level_item_of_crate(intr: @ident_interner,
cdata: cmd,
get_crate_data: GetCrateDataCb,
callback: &fn(def_like, ast::ident)) {
let root_doc = reader::Doc(cdata.data);
let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
let crate_items_doc = reader::get_doc(misc_info_doc,
tag_misc_info_crate_items);
let mut path_builder = ~"";
let mut context = EachItemContext {
intr: intr,
cdata: cdata,
get_crate_data: get_crate_data,
path_builder: &mut path_builder,
callback: f,
};
// Iterate over all top-level crate items.
context.each_child_of_module_or_crate(crate_items_doc)
each_child_of_item_or_crate(intr,
cdata,
crate_items_doc,
get_crate_data,
callback)
}
pub fn get_item_path(cdata: cmd, id: ast::NodeId) -> ast_map::path {
@ -1268,21 +1349,6 @@ pub fn get_crate_vers(data: @~[u8]) -> @str {
}
}
fn iter_crate_items(intr: @ident_interner, cdata: cmd,
get_crate_data: GetCrateDataCb,
proc: &fn(path: &str, ast::def_id)) {
do each_path(intr, cdata, get_crate_data) |path_string, def_like, _| {
match def_like {
dl_impl(*) | dl_field => {}
dl_def(def) => {
proc(path_string,
ast_util::def_id_of_def(def))
}
}
true
};
}
pub fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8],
out: @io::Writer) {
let hash = get_crate_hash(bytes);

View File

@ -10,10 +10,11 @@
use driver::session::Session;
use metadata::csearch::{each_path, get_trait_method_def_ids};
use metadata::csearch::get_trait_method_def_ids;
use metadata::csearch::get_method_name_and_explicit_self;
use metadata::csearch::get_static_methods_if_impl;
use metadata::csearch::{get_type_name_if_impl, get_struct_fields};
use metadata::csearch;
use metadata::cstore::find_extern_mod_stmt_cnum;
use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
use middle::lang_items::LanguageItems;
@ -486,7 +487,7 @@ pub fn Module(parent_link: ParentLink,
anonymous_children: @mut HashMap::new(),
import_resolutions: @mut HashMap::new(),
glob_count: 0,
resolved_import_count: 0
resolved_import_count: 0,
}
}
@ -1629,14 +1630,13 @@ impl Resolver {
visit::walk_block(visitor, block, new_parent);
}
pub fn handle_external_def(@mut self,
def: def,
visibility: ast::visibility,
modules: &mut HashMap<def_id, @mut Module>,
child_name_bindings: @mut NameBindings,
final_ident: &str,
ident: ident,
new_parent: ReducedGraphParent) {
fn handle_external_def(@mut self,
def: def,
visibility: ast::visibility,
child_name_bindings: @mut NameBindings,
final_ident: &str,
ident: ident,
new_parent: ReducedGraphParent) {
let privacy = visibility_to_privacy(visibility);
match def {
def_mod(def_id) | def_foreign_mod(def_id) => {
@ -1645,7 +1645,6 @@ impl Resolver {
debug!("(building reduced graph for external crate) \
already created module");
module_def.def_id = Some(def_id);
modules.insert(def_id, module_def);
}
Some(_) | None => {
debug!("(building reduced graph for \
@ -1653,42 +1652,11 @@ impl Resolver {
%s", final_ident);
let parent_link = self.get_parent_link(new_parent, ident);
// FIXME (#5074): this should be a match on find
if !modules.contains_key(&def_id) {
child_name_bindings.define_module(privacy,
parent_link,
Some(def_id),
NormalModuleKind,
dummy_sp());
modules.insert(def_id,
child_name_bindings.get_module());
} else {
let existing_module = *modules.get(&def_id);
// Create an import resolution to avoid creating cycles in
// the module graph.
let resolution = @mut ImportResolution(Public, 0);
resolution.outstanding_references = 0;
match existing_module.parent_link {
NoParentLink |
BlockParentLink(*) => {
fail!("can't happen");
}
ModuleParentLink(parent_module, ident) => {
let name_bindings = parent_module.children.get(
&ident);
resolution.type_target =
Some(Target(parent_module, *name_bindings));
}
}
debug!("(building reduced graph for external crate) \
... creating import resolution");
new_parent.import_resolutions.insert(ident, resolution);
}
child_name_bindings.define_module(privacy,
parent_link,
Some(def_id),
NormalModuleKind,
dummy_sp());
}
}
}
@ -1779,184 +1747,160 @@ impl Resolver {
}
}
/**
* Builds the reduced graph rooted at the 'use' directive for an external
* crate.
*/
pub fn build_reduced_graph_for_external_crate(@mut self,
root: @mut Module) {
let mut modules = HashMap::new();
/// Builds the reduced graph for a single item in an external crate.
fn build_reduced_graph_for_external_crate_def(@mut self,
root: @mut Module,
def_like: def_like,
ident: ident) {
match def_like {
dl_def(def) => {
// Add the new child item, if necessary.
let optional_module = match def {
def_foreign_mod(*) => Some(root),
_ => {
let (child_name_bindings, new_parent) =
self.add_child(ident,
ModuleReducedGraphParent(root),
OverwriteDuplicates,
dummy_sp());
// Create all the items reachable by paths.
do each_path(self.session.cstore, root.def_id.unwrap().crate)
|path_string, def_like, visibility| {
self.handle_external_def(def,
public,
child_name_bindings,
self.session.str_of(ident),
ident,
new_parent);
debug!("(building reduced graph for external crate) found path \
entry: %s (%?)",
path_string, def_like);
/*println(fmt!(">>> child item added: %s",
self.session.str_of(ident)));*/
let mut pieces: ~[&str] = path_string.split_str_iter("::").collect();
let final_ident_str = pieces.pop();
let final_ident = self.session.ident_of(final_ident_str);
// Find the module we need, creating modules along the way if we
// need to.
let mut current_module = root;
for ident_str in pieces.iter() {
let ident = self.session.ident_of(*ident_str);
// Create or reuse a graph node for the child.
let (child_name_bindings, new_parent) =
self.add_child(ident,
ModuleReducedGraphParent(current_module),
OverwriteDuplicates,
dummy_sp());
// Define or reuse the module node.
match child_name_bindings.type_def {
None => {
debug!("(building reduced graph for external crate) \
autovivifying missing type def %s",
*ident_str);
let parent_link = self.get_parent_link(new_parent,
ident);
child_name_bindings.define_module(Public,
parent_link,
None,
NormalModuleKind,
dummy_sp());
child_name_bindings.get_module_if_available()
}
Some(type_ns_def)
if type_ns_def.module_def.is_none() => {
debug!("(building reduced graph for external crate) \
autovivifying missing module def %s",
*ident_str);
let parent_link = self.get_parent_link(new_parent,
ident);
child_name_bindings.define_module(Public,
parent_link,
None,
NormalModuleKind,
dummy_sp());
}
_ => {} // Fall through.
}
};
current_module = child_name_bindings.get_module();
}
match def_like {
dl_def(def) => {
// Add the new child item.
let (child_name_bindings, new_parent) =
self.add_child(final_ident,
ModuleReducedGraphParent(
current_module),
OverwriteDuplicates,
dummy_sp());
self.handle_external_def(def,
visibility,
&mut modules,
child_name_bindings,
self.session.str_of(
final_ident),
final_ident,
new_parent);
}
dl_impl(def) => {
// We only process static methods of impls here.
match get_type_name_if_impl(self.session.cstore, def) {
None => {}
Some(final_ident) => {
let static_methods_opt =
get_static_methods_if_impl(
self.session.cstore, def);
match static_methods_opt {
Some(ref static_methods) if
static_methods.len() >= 1 => {
debug!("(building reduced graph for \
external crate) processing \
static methods for type name %s",
self.session.str_of(
final_ident));
let (child_name_bindings, new_parent) =
self.add_child(final_ident,
ModuleReducedGraphParent(
current_module),
OverwriteDuplicates,
dummy_sp());
// Process the static methods. First,
// create the module.
let type_module;
match child_name_bindings.type_def {
Some(TypeNsDef {
module_def: Some(module_def),
_
}) => {
// We already have a module. This
// is OK.
type_module = module_def;
// Mark it as an impl module if
// necessary.
type_module.kind = ImplModuleKind;
}
Some(_) | None => {
let parent_link =
self.get_parent_link(
new_parent, final_ident);
child_name_bindings.define_module(
Public,
parent_link,
Some(def),
ImplModuleKind,
dummy_sp());
type_module =
child_name_bindings.
get_module();
}
}
// Add each static method to the module.
let new_parent = ModuleReducedGraphParent(
type_module);
for static_method_info in static_methods.iter() {
let ident = static_method_info.ident;
debug!("(building reduced graph for \
external crate) creating \
static method '%s'",
self.session.str_of(ident));
let (method_name_bindings, _) =
self.add_child(
ident,
new_parent,
OverwriteDuplicates,
dummy_sp());
let def = def_fn(
static_method_info.def_id,
static_method_info.purity);
method_name_bindings.define_value(
Public, def, dummy_sp());
}
}
// Otherwise, do nothing.
Some(_) | None => {}
}
match optional_module {
None => {}
Some(module) => {
do csearch::each_child_of_item(self.session.cstore,
def_id_of_def(def))
|def_like, child_ident| {
/*println(fmt!(">>> each_child_of_item: %s %s",
self.session.str_of(ident),
self.session.str_of(child_ident)));*/
self.build_reduced_graph_for_external_crate_def(
module,
def_like,
child_ident)
}
}
}
dl_field => {
debug!("(building reduced graph for external crate) \
ignoring field");
}
dl_impl(def) => {
// We only process static methods of impls here.
match get_type_name_if_impl(self.session.cstore, def) {
None => {}
Some(final_ident) => {
let static_methods_opt =
get_static_methods_if_impl(self.session.cstore,
def);
match static_methods_opt {
Some(ref static_methods) if
static_methods.len() >= 1 => {
debug!("(building reduced graph for \
external crate) processing \
static methods for type name %s",
self.session.str_of(
final_ident));
let (child_name_bindings, new_parent) =
self.add_child(
final_ident,
ModuleReducedGraphParent(root),
OverwriteDuplicates,
dummy_sp());
// Process the static methods. First,
// create the module.
let type_module;
match child_name_bindings.type_def {
Some(TypeNsDef {
module_def: Some(module_def),
_
}) => {
// We already have a module. This
// is OK.
type_module = module_def;
// Mark it as an impl module if
// necessary.
type_module.kind = ImplModuleKind;
}
Some(_) | None => {
let parent_link =
self.get_parent_link(new_parent,
final_ident);
child_name_bindings.define_module(
Public,
parent_link,
Some(def),
ImplModuleKind,
dummy_sp());
type_module =
child_name_bindings.
get_module();
}
}
// Add each static method to the module.
let new_parent =
ModuleReducedGraphParent(type_module);
for static_method_info in
static_methods.iter() {
let ident = static_method_info.ident;
debug!("(building reduced graph for \
external crate) creating \
static method '%s'",
self.session.str_of(ident));
let (method_name_bindings, _) =
self.add_child(ident,
new_parent,
OverwriteDuplicates,
dummy_sp());
let def = def_fn(
static_method_info.def_id,
static_method_info.purity);
method_name_bindings.define_value(
Public,
def,
dummy_sp());
}
}
// Otherwise, do nothing.
Some(_) | None => {}
}
}
}
}
true
};
dl_field => {
debug!("(building reduced graph for external crate) \
ignoring field");
}
}
}
/// Builds the reduced graph rooted at the 'use' directive for an external
/// crate.
pub fn build_reduced_graph_for_external_crate(@mut self,
root: @mut Module) {
do csearch::each_top_level_item_of_crate(self.session.cstore,
root.def_id.unwrap().crate)
|def_like, ident| {
self.build_reduced_graph_for_external_crate_def(root,
def_like,
ident)
}
}
/// Creates and adds an import directive to the given module.