1
Fork 0

Peform def id assignment during expansion.

This commit is contained in:
Jeffrey Seyfried 2016-09-14 09:55:20 +00:00
parent d0623cf7bd
commit ebaaafcd5d
6 changed files with 106 additions and 53 deletions

View file

@ -18,31 +18,33 @@ use middle::cstore::InlinedItem;
use syntax::ast::*; use syntax::ast::*;
use syntax::visit; use syntax::visit;
use syntax::parse::token; use syntax::parse::token::{self, keywords};
/// Creates def ids for nodes in the HIR. /// Creates def ids for nodes in the HIR.
pub struct DefCollector<'ast> { pub struct DefCollector<'a> {
// If we are walking HIR (c.f., AST), we need to keep a reference to the // If we are walking HIR (c.f., AST), we need to keep a reference to the
// crate. // crate.
hir_crate: Option<&'ast hir::Crate>, hir_crate: Option<&'a hir::Crate>,
definitions: &'ast mut Definitions, definitions: &'a mut Definitions,
parent_def: Option<DefIndex>, parent_def: Option<DefIndex>,
pub visit_macro_invoc: Option<&'a mut FnMut(NodeId, DefIndex)>,
} }
impl<'ast> DefCollector<'ast> { impl<'a> DefCollector<'a> {
pub fn new(definitions: &'ast mut Definitions) -> DefCollector<'ast> { pub fn new(definitions: &'a mut Definitions) -> Self {
DefCollector { DefCollector {
hir_crate: None, hir_crate: None,
definitions: definitions, definitions: definitions,
parent_def: None, parent_def: None,
visit_macro_invoc: None,
} }
} }
pub fn extend(parent_node: NodeId, pub fn extend(parent_node: NodeId,
parent_def_path: DefPath, parent_def_path: DefPath,
parent_def_id: DefId, parent_def_id: DefId,
definitions: &'ast mut Definitions) definitions: &'a mut Definitions)
-> DefCollector<'ast> { -> Self {
let mut collector = DefCollector::new(definitions); let mut collector = DefCollector::new(definitions);
assert_eq!(parent_def_path.krate, parent_def_id.krate); assert_eq!(parent_def_path.krate, parent_def_id.krate);
@ -65,7 +67,7 @@ impl<'ast> DefCollector<'ast> {
self.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc); self.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
} }
pub fn walk_item(&mut self, ii: &'ast InlinedItem, krate: &'ast hir::Crate) { pub fn walk_item(&mut self, ii: &'a InlinedItem, krate: &'a hir::Crate) {
self.hir_crate = Some(krate); self.hir_crate = Some(krate);
ii.visit(self); ii.visit(self);
} }
@ -84,7 +86,7 @@ impl<'ast> DefCollector<'ast> {
self.definitions.create_def_with_parent(parent, node_id, data) self.definitions.create_def_with_parent(parent, node_id, data)
} }
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) { pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
let parent = self.parent_def; let parent = self.parent_def;
self.parent_def = Some(parent_def); self.parent_def = Some(parent_def);
f(self); f(self);
@ -106,7 +108,7 @@ impl<'ast> DefCollector<'ast> {
self.create_def(expr.id, DefPathData::Initializer); self.create_def(expr.id, DefPathData::Initializer);
} }
fn visit_hir_const_integer(&mut self, expr: &'ast hir::Expr) { fn visit_hir_const_integer(&mut self, expr: &hir::Expr) {
// FIXME(eddyb) Closures should have separate // FIXME(eddyb) Closures should have separate
// function definition IDs and expression IDs. // function definition IDs and expression IDs.
if let hir::ExprClosure(..) = expr.node { if let hir::ExprClosure(..) = expr.node {
@ -115,9 +117,15 @@ impl<'ast> DefCollector<'ast> {
self.create_def(expr.id, DefPathData::Initializer); self.create_def(expr.id, DefPathData::Initializer);
} }
fn visit_macro_invoc(&mut self, id: NodeId) {
if let Some(ref mut visit) = self.visit_macro_invoc {
visit(id, self.parent_def.unwrap());
}
}
} }
impl<'ast> visit::Visitor for DefCollector<'ast> { impl<'a> visit::Visitor for DefCollector<'a> {
fn visit_item(&mut self, i: &Item) { fn visit_item(&mut self, i: &Item) {
debug!("visit_item: {:?}", i); debug!("visit_item: {:?}", i);
@ -129,10 +137,14 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
DefPathData::TypeNs(i.ident.name.as_str()), DefPathData::TypeNs(i.ident.name.as_str()),
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()), ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
DefPathData::ValueNs(i.ident.name.as_str()), DefPathData::ValueNs(i.ident.name.as_str()),
ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name.as_str()), ItemKind::Mac(..) if i.id == DUMMY_NODE_ID => return, // Scope placeholder
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
ItemKind::Use(..) => DefPathData::Misc, ItemKind::Use(..) => DefPathData::Misc,
}; };
let def = self.create_def(i.id, def_data); let def = self.create_def(i.id, def_data);
@ -198,7 +210,7 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
TraitItemKind::Method(..) | TraitItemKind::Const(..) => TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
DefPathData::ValueNs(ti.ident.name.as_str()), DefPathData::ValueNs(ti.ident.name.as_str()),
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()), TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
TraitItemKind::Macro(..) => DefPathData::MacroDef(ti.ident.name.as_str()), TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
}; };
let def = self.create_def(ti.id, def_data); let def = self.create_def(ti.id, def_data);
@ -216,7 +228,7 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
ImplItemKind::Method(..) | ImplItemKind::Const(..) => ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name.as_str()), DefPathData::ValueNs(ii.ident.name.as_str()),
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()), ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
ImplItemKind::Macro(..) => DefPathData::MacroDef(ii.ident.name.as_str()), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
}; };
let def = self.create_def(ii.id, def_data); let def = self.create_def(ii.id, def_data);
@ -232,9 +244,13 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
fn visit_pat(&mut self, pat: &Pat) { fn visit_pat(&mut self, pat: &Pat) {
let parent_def = self.parent_def; let parent_def = self.parent_def;
if let PatKind::Ident(_, id, _) = pat.node { match pat.node {
let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str())); PatKind::Mac(..) => return self.visit_macro_invoc(pat.id),
self.parent_def = Some(def); PatKind::Ident(_, id, _) => {
let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str()));
self.parent_def = Some(def);
}
_ => {}
} }
visit::walk_pat(self, pat); visit::walk_pat(self, pat);
@ -244,13 +260,14 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
fn visit_expr(&mut self, expr: &Expr) { fn visit_expr(&mut self, expr: &Expr) {
let parent_def = self.parent_def; let parent_def = self.parent_def;
if let ExprKind::Repeat(_, ref count) = expr.node { match expr.node {
self.visit_ast_const_integer(count); ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
} ExprKind::Repeat(_, ref count) => self.visit_ast_const_integer(count),
ExprKind::Closure(..) => {
if let ExprKind::Closure(..) = expr.node { let def = self.create_def(expr.id, DefPathData::ClosureExpr);
let def = self.create_def(expr.id, DefPathData::ClosureExpr); self.parent_def = Some(def);
self.parent_def = Some(def); }
_ => {}
} }
visit::walk_expr(self, expr); visit::walk_expr(self, expr);
@ -258,11 +275,13 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
} }
fn visit_ty(&mut self, ty: &Ty) { fn visit_ty(&mut self, ty: &Ty) {
if let TyKind::FixedLengthVec(_, ref length) = ty.node { match ty.node {
self.visit_ast_const_integer(length); TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
} TyKind::FixedLengthVec(_, ref length) => self.visit_ast_const_integer(length),
if let TyKind::ImplTrait(..) = ty.node { TyKind::ImplTrait(..) => {
self.create_def(ty.id, DefPathData::ImplTrait); self.create_def(ty.id, DefPathData::ImplTrait);
}
_ => {}
} }
visit::walk_ty(self, ty); visit::walk_ty(self, ty);
} }
@ -274,6 +293,13 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
fn visit_macro_def(&mut self, macro_def: &MacroDef) { fn visit_macro_def(&mut self, macro_def: &MacroDef) {
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name.as_str())); self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name.as_str()));
} }
fn visit_stmt(&mut self, stmt: &Stmt) {
match stmt.node {
StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id),
_ => visit::walk_stmt(self, stmt),
}
}
} }
// We walk the HIR rather than the AST when reading items from metadata. // We walk the HIR rather than the AST when reading items from metadata.

View file

@ -9,11 +9,10 @@
// except according to those terms. // except according to those terms.
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use hir::map::def_collector::DefCollector;
use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::fnv::FnvHashMap;
use std::fmt::Write; use std::fmt::Write;
use std::hash::{Hash, Hasher, SipHasher}; use std::hash::{Hash, Hasher, SipHasher};
use syntax::{ast, visit}; use syntax::ast;
use syntax::parse::token::{self, InternedString}; use syntax::parse::token::{self, InternedString};
use ty::TyCtxt; use ty::TyCtxt;
use util::nodemap::NodeMap; use util::nodemap::NodeMap;
@ -224,12 +223,6 @@ impl Definitions {
} }
} }
pub fn collect(&mut self, krate: &ast::Crate) {
let mut def_collector = DefCollector::new(self);
def_collector.collect_root();
visit::walk_crate(&mut def_collector, krate);
}
/// Get the number of definitions. /// Get the number of definitions.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.data.len() self.data.len()

View file

@ -11,7 +11,7 @@
pub use self::Node::*; pub use self::Node::*;
use self::MapEntry::*; use self::MapEntry::*;
use self::collector::NodeCollector; use self::collector::NodeCollector;
use self::def_collector::DefCollector; pub use self::def_collector::DefCollector;
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
DisambiguatedDefPathData, InlinedRootPath}; DisambiguatedDefPathData, InlinedRootPath};

View file

@ -733,9 +733,6 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
}) })
})?; })?;
// Collect defintions for def ids.
time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate));
time(sess.time_passes(), time(sess.time_passes(),
"early lint checks", "early lint checks",
|| lint::check_ast_crate(sess, &krate)); || lint::check_ast_crate(sess, &krate));

View file

@ -42,7 +42,7 @@ use self::RibKind::*;
use self::UseLexicalScopeFlag::*; use self::UseLexicalScopeFlag::*;
use self::ModulePrefixResult::*; use self::ModulePrefixResult::*;
use rustc::hir::map::Definitions; use rustc::hir::map::{Definitions, DefCollector};
use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
use rustc::middle::cstore::CrateLoader; use rustc::middle::cstore::CrateLoader;
use rustc::session::Session; use rustc::session::Session;
@ -1188,13 +1188,16 @@ impl<'a> Resolver<'a> {
let mut module_map = NodeMap(); let mut module_map = NodeMap();
module_map.insert(CRATE_NODE_ID, graph_root); module_map.insert(CRATE_NODE_ID, graph_root);
let mut definitions = Definitions::new();
DefCollector::new(&mut definitions).collect_root();
let mut expansion_data = FnvHashMap(); let mut expansion_data = FnvHashMap();
expansion_data.insert(0, macros::ExpansionData::default()); // Crate root expansion expansion_data.insert(0, macros::ExpansionData::root()); // Crate root expansion
Resolver { Resolver {
session: session, session: session,
definitions: Definitions::new(), definitions: definitions,
macros_at_scope: FnvHashMap(), macros_at_scope: FnvHashMap(),
// The outermost module has def ID 0; this is not reflected in the // The outermost module has def ID 0; this is not reflected in the
@ -1264,6 +1267,13 @@ impl<'a> Resolver<'a> {
/// Entry point to crate resolution. /// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) { pub fn resolve_crate(&mut self, krate: &Crate) {
// Collect `DefId`s for exported macro defs.
for def in &krate.exported_macros {
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
collector.visit_macro_def(def)
})
}
self.current_module = self.graph_root; self.current_module = self.graph_root;
visit::walk_crate(self, krate); visit::walk_crate(self, krate);

View file

@ -9,6 +9,8 @@
// except according to those terms. // except according to those terms.
use Resolver; use Resolver;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefIndex};
use rustc::hir::map::DefCollector;
use rustc::middle::cstore::LoadedMacro; use rustc::middle::cstore::LoadedMacro;
use rustc::util::nodemap::FnvHashMap; use rustc::util::nodemap::FnvHashMap;
use std::cell::RefCell; use std::cell::RefCell;
@ -27,9 +29,19 @@ use syntax::util::lev_distance::find_best_match_for_name;
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
use syntax_pos::Span; use syntax_pos::Span;
#[derive(Clone, Default)] #[derive(Clone)]
pub struct ExpansionData { pub struct ExpansionData {
module: Rc<ModuleData>, module: Rc<ModuleData>,
def_index: DefIndex,
}
impl ExpansionData {
pub fn root() -> Self {
ExpansionData {
module: Default::default(),
def_index: CRATE_DEF_INDEX,
}
}
} }
// FIXME(jseyfried): merge with `::ModuleS`. // FIXME(jseyfried): merge with `::ModuleS`.
@ -46,10 +58,10 @@ impl<'a> base::Resolver for Resolver<'a> {
} }
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) { fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
expansion.visit_with(&mut ExpansionVisitor { let module = self.expansion_data[&mark.as_u32()].module.clone();
current_module: self.expansion_data[&mark.as_u32()].module.clone(), let mut visitor = ExpansionVisitor { current_module: module, resolver: self };
resolver: self, visitor.collect_def_ids(mark, expansion);
}); expansion.visit_with(&mut visitor);
} }
fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) {
@ -166,9 +178,8 @@ struct ExpansionVisitor<'b, 'a: 'b> {
impl<'a, 'b> ExpansionVisitor<'a, 'b> { impl<'a, 'b> ExpansionVisitor<'a, 'b> {
fn visit_invoc(&mut self, id: ast::NodeId) { fn visit_invoc(&mut self, id: ast::NodeId) {
self.resolver.expansion_data.insert(id.as_u32(), ExpansionData { self.resolver.expansion_data.get_mut(&id.as_u32()).unwrap().module =
module: self.current_module.clone(), self.current_module.clone();
});
} }
// does this attribute list contain "macro_use"? // does this attribute list contain "macro_use"?
@ -195,6 +206,22 @@ impl<'a, 'b> ExpansionVisitor<'a, 'b> {
false false
} }
fn collect_def_ids(&mut self, mark: Mark, expansion: &Expansion) {
let expansion_data = &mut self.resolver.expansion_data;
let module = &self.current_module;
let def_index = expansion_data[&mark.as_u32()].def_index;
let visit_macro_invoc = &mut |id: ast::NodeId, def_index| {
expansion_data.insert(id.as_u32(), ExpansionData {
def_index: def_index,
module: module.clone(),
});
};
let mut def_collector = DefCollector::new(&mut self.resolver.definitions);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| expansion.visit_with(def_collector));
}
} }
macro_rules! method { macro_rules! method {