mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-20 11:43:04 +00:00
HIR visitor for DefCollector
So that we can work with inlined HIR from metadata.
This commit is contained in:
parent
0c37d4bb1d
commit
744be0b5aa
@ -10,20 +10,28 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
use hir;
|
||||
use hir::intravisit;
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
|
||||
|
||||
use middle::cstore::InlinedItem;
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::visit;
|
||||
|
||||
/// Creates def ids for nodes in the HIR.
|
||||
pub struct DefCollector {
|
||||
pub struct DefCollector<'ast> {
|
||||
// If we are walking HIR (c.f., AST), we need to keep a reference to the
|
||||
// crate.
|
||||
hir_crate: Option<&'ast hir::Crate>,
|
||||
pub definitions: Definitions,
|
||||
pub parent_def: Option<DefIndex>,
|
||||
parent_def: Option<DefIndex>,
|
||||
}
|
||||
|
||||
impl DefCollector {
|
||||
pub fn root() -> DefCollector {
|
||||
impl<'ast> DefCollector<'ast> {
|
||||
pub fn root() -> DefCollector<'ast> {
|
||||
let mut collector = DefCollector {
|
||||
hir_crate: None,
|
||||
definitions: Definitions::new(),
|
||||
parent_def: None,
|
||||
};
|
||||
@ -39,8 +47,9 @@ impl DefCollector {
|
||||
parent_def_path: DefPath,
|
||||
parent_def_id: DefId,
|
||||
definitions: Definitions)
|
||||
-> DefCollector {
|
||||
-> DefCollector<'ast> {
|
||||
let mut collector = DefCollector {
|
||||
hir_crate: None,
|
||||
parent_def: None,
|
||||
definitions: definitions,
|
||||
};
|
||||
@ -57,6 +66,11 @@ impl DefCollector {
|
||||
collector
|
||||
}
|
||||
|
||||
pub fn walk_item(&mut self, ii: &'ast InlinedItem, krate: &'ast hir::Crate) {
|
||||
self.hir_crate = Some(krate);
|
||||
ii.visit(self);
|
||||
}
|
||||
|
||||
fn parent_def(&self) -> Option<DefIndex> {
|
||||
self.parent_def
|
||||
}
|
||||
@ -83,7 +97,7 @@ impl DefCollector {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> visit::Visitor<'ast> for DefCollector {
|
||||
impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
|
||||
fn visit_item(&mut self, i: &'ast Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
@ -226,3 +240,151 @@ impl<'ast> visit::Visitor<'ast> for DefCollector {
|
||||
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name));
|
||||
}
|
||||
}
|
||||
|
||||
// We walk the HIR rather than the AST when reading items from metadata.
|
||||
impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
|
||||
/// Because we want to track parent items and so forth, enable
|
||||
/// deep walking so that we walk nested items in the context of
|
||||
/// their outer items.
|
||||
fn visit_nested_item(&mut self, item_id: hir::ItemId) {
|
||||
debug!("visit_nested_item: {:?}", item_id);
|
||||
let item = self.hir_crate.unwrap().item(item_id.id);
|
||||
self.visit_item(item)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'ast hir::Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
// Pick the def data. This need not be unique, but the more
|
||||
// information we encapsulate into
|
||||
let def_data = match i.node {
|
||||
hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
|
||||
DefPathData::Impl,
|
||||
hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
|
||||
hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
|
||||
hir::ItemTy(..) =>
|
||||
DefPathData::TypeNs(i.name),
|
||||
hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
|
||||
DefPathData::ValueNs(i.name),
|
||||
hir::ItemUse(..) => DefPathData::Misc,
|
||||
};
|
||||
let def = self.create_def(i.id, def_data);
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
match i.node {
|
||||
hir::ItemEnum(ref enum_definition, _) => {
|
||||
for v in &enum_definition.variants {
|
||||
let variant_def_index =
|
||||
this.create_def(v.node.data.id(),
|
||||
DefPathData::EnumVariant(v.node.name));
|
||||
|
||||
for field in v.node.data.fields() {
|
||||
this.create_def_with_parent(Some(variant_def_index),
|
||||
field.id,
|
||||
DefPathData::Field(field.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemStruct(ref struct_def, _) => {
|
||||
// If this is a tuple-like struct, register the constructor.
|
||||
if !struct_def.is_struct() {
|
||||
this.create_def(struct_def.id(),
|
||||
DefPathData::StructCtor);
|
||||
}
|
||||
|
||||
for field in struct_def.fields() {
|
||||
this.create_def(field.id, DefPathData::Field(field.name));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
intravisit::walk_item(this, i);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
|
||||
let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
intravisit::walk_foreign_item(this, foreign_item);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'ast hir::Generics) {
|
||||
for ty_param in generics.ty_params.iter() {
|
||||
self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name));
|
||||
}
|
||||
|
||||
intravisit::walk_generics(self, generics);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
|
||||
let def_data = match ti.node {
|
||||
hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
|
||||
DefPathData::ValueNs(ti.name),
|
||||
hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
|
||||
};
|
||||
|
||||
let def = self.create_def(ti.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
intravisit::walk_trait_item(this, ti);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
|
||||
let def_data = match ii.node {
|
||||
hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
|
||||
DefPathData::ValueNs(ii.name),
|
||||
hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
|
||||
};
|
||||
|
||||
let def = self.create_def(ii.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
intravisit::walk_impl_item(this, ii);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &'ast hir::Pat) {
|
||||
let maybe_binding = match pat.node {
|
||||
hir::PatKind::Ident(_, id, _) => Some(id.node),
|
||||
_ => None
|
||||
};
|
||||
|
||||
let parent_def = self.parent_def;
|
||||
if let Some(id) = maybe_binding {
|
||||
let def = self.create_def(pat.id, DefPathData::Binding(id.name));
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
||||
intravisit::walk_pat(self, pat);
|
||||
self.parent_def = parent_def;
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
|
||||
let parent_def = self.parent_def;
|
||||
|
||||
if let hir::ExprClosure(..) = expr.node {
|
||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
||||
intravisit::walk_expr(self, expr);
|
||||
self.parent_def = parent_def;
|
||||
}
|
||||
|
||||
fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
|
||||
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
|
||||
}
|
||||
|
||||
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
|
||||
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
|
||||
}
|
||||
}
|
@ -843,14 +843,13 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
||||
let ii = map.forest.inlined_items.alloc(ii);
|
||||
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
|
||||
|
||||
// TODO need to save defs in metadata :-(
|
||||
// let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
|
||||
// let mut def_collector = DefCollector::extend(ii_parent_id,
|
||||
// parent_def_path.clone(),
|
||||
// parent_def_id,
|
||||
// defs);
|
||||
// ii.visit(&mut def_collector);
|
||||
// *map.definitions.borrow_mut() = def_collector.definitions;
|
||||
let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
|
||||
let mut def_collector = DefCollector::extend(ii_parent_id,
|
||||
parent_def_path.clone(),
|
||||
parent_def_id,
|
||||
defs);
|
||||
def_collector.walk_item(ii, map.krate());
|
||||
*map.definitions.borrow_mut() = def_collector.definitions;
|
||||
|
||||
let mut collector = NodeCollector::extend(map.krate(),
|
||||
ii,
|
||||
|
Loading…
Reference in New Issue
Block a user