From ebaaafcd5d9c71745bfb489e51b074ce00d2e158 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried <jeffrey.seyfried@gmail.com> Date: Wed, 14 Sep 2016 09:55:20 +0000 Subject: [PATCH] Peform def id assignment during expansion. --- src/librustc/hir/map/def_collector.rs | 86 +++++++++++++++++---------- src/librustc/hir/map/definitions.rs | 9 +-- src/librustc/hir/map/mod.rs | 2 +- src/librustc_driver/driver.rs | 3 - src/librustc_resolve/lib.rs | 16 ++++- src/librustc_resolve/macros.rs | 43 +++++++++++--- 6 files changed, 106 insertions(+), 53 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index b0a717e18f9..1fb078ec325 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -18,31 +18,33 @@ use middle::cstore::InlinedItem; use syntax::ast::*; use syntax::visit; -use syntax::parse::token; +use syntax::parse::token::{self, keywords}; /// 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 // crate. - hir_crate: Option<&'ast hir::Crate>, - definitions: &'ast mut Definitions, + hir_crate: Option<&'a hir::Crate>, + definitions: &'a mut Definitions, parent_def: Option<DefIndex>, + pub visit_macro_invoc: Option<&'a mut FnMut(NodeId, DefIndex)>, } -impl<'ast> DefCollector<'ast> { - pub fn new(definitions: &'ast mut Definitions) -> DefCollector<'ast> { +impl<'a> DefCollector<'a> { + pub fn new(definitions: &'a mut Definitions) -> Self { DefCollector { hir_crate: None, definitions: definitions, parent_def: None, + visit_macro_invoc: None, } } pub fn extend(parent_node: NodeId, parent_def_path: DefPath, parent_def_id: DefId, - definitions: &'ast mut Definitions) - -> DefCollector<'ast> { + definitions: &'a mut Definitions) + -> Self { let mut collector = DefCollector::new(definitions); 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); } - 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); ii.visit(self); } @@ -84,7 +86,7 @@ impl<'ast> DefCollector<'ast> { 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; self.parent_def = Some(parent_def); f(self); @@ -106,7 +108,7 @@ impl<'ast> DefCollector<'ast> { 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 // function definition IDs and expression IDs. if let hir::ExprClosure(..) = expr.node { @@ -115,9 +117,15 @@ impl<'ast> DefCollector<'ast> { 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) { debug!("visit_item: {:?}", i); @@ -129,10 +137,14 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => 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::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => 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, }; let def = self.create_def(i.id, def_data); @@ -198,7 +210,7 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { TraitItemKind::Method(..) | TraitItemKind::Const(..) => DefPathData::ValueNs(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); @@ -216,7 +228,7 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(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); @@ -232,9 +244,13 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { fn visit_pat(&mut self, pat: &Pat) { let parent_def = self.parent_def; - if let PatKind::Ident(_, id, _) = pat.node { - let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str())); - self.parent_def = Some(def); + match pat.node { + PatKind::Mac(..) => return self.visit_macro_invoc(pat.id), + 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); @@ -244,13 +260,14 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { fn visit_expr(&mut self, expr: &Expr) { let parent_def = self.parent_def; - if let ExprKind::Repeat(_, ref count) = expr.node { - self.visit_ast_const_integer(count); - } - - if let ExprKind::Closure(..) = expr.node { - let def = self.create_def(expr.id, DefPathData::ClosureExpr); - self.parent_def = Some(def); + match expr.node { + ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), + ExprKind::Repeat(_, ref count) => self.visit_ast_const_integer(count), + ExprKind::Closure(..) => { + let def = self.create_def(expr.id, DefPathData::ClosureExpr); + self.parent_def = Some(def); + } + _ => {} } visit::walk_expr(self, expr); @@ -258,11 +275,13 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { } fn visit_ty(&mut self, ty: &Ty) { - if let TyKind::FixedLengthVec(_, ref length) = ty.node { - self.visit_ast_const_integer(length); - } - if let TyKind::ImplTrait(..) = ty.node { - self.create_def(ty.id, DefPathData::ImplTrait); + match ty.node { + TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), + TyKind::FixedLengthVec(_, ref length) => self.visit_ast_const_integer(length), + TyKind::ImplTrait(..) => { + self.create_def(ty.id, DefPathData::ImplTrait); + } + _ => {} } 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) { 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. diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 5cfb71f4fc8..f87844652cc 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -9,11 +9,10 @@ // except according to those terms. use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; -use hir::map::def_collector::DefCollector; use rustc_data_structures::fnv::FnvHashMap; use std::fmt::Write; use std::hash::{Hash, Hasher, SipHasher}; -use syntax::{ast, visit}; +use syntax::ast; use syntax::parse::token::{self, InternedString}; use ty::TyCtxt; 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. pub fn len(&self) -> usize { self.data.len() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b351bd427ac..cd085177ed7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -11,7 +11,7 @@ pub use self::Node::*; use self::MapEntry::*; use self::collector::NodeCollector; -use self::def_collector::DefCollector; +pub use self::def_collector::DefCollector; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, InlinedRootPath}; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9d5dce7ad05..226eb545d2c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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(), "early lint checks", || lint::check_ast_crate(sess, &krate)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index fb9819b72ab..467967a4f33 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -42,7 +42,7 @@ use self::RibKind::*; use self::UseLexicalScopeFlag::*; 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::middle::cstore::CrateLoader; use rustc::session::Session; @@ -1188,13 +1188,16 @@ impl<'a> Resolver<'a> { let mut module_map = NodeMap(); module_map.insert(CRATE_NODE_ID, graph_root); + let mut definitions = Definitions::new(); + DefCollector::new(&mut definitions).collect_root(); + 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 { session: session, - definitions: Definitions::new(), + definitions: definitions, macros_at_scope: FnvHashMap(), // 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. 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; visit::walk_crate(self, krate); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3a9fb845190..ebfdc32fabd 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -9,6 +9,8 @@ // except according to those terms. use Resolver; +use rustc::hir::def_id::{CRATE_DEF_INDEX, DefIndex}; +use rustc::hir::map::DefCollector; use rustc::middle::cstore::LoadedMacro; use rustc::util::nodemap::FnvHashMap; 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_pos::Span; -#[derive(Clone, Default)] +#[derive(Clone)] pub struct ExpansionData { 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`. @@ -46,10 +58,10 @@ impl<'a> base::Resolver for Resolver<'a> { } fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) { - expansion.visit_with(&mut ExpansionVisitor { - current_module: self.expansion_data[&mark.as_u32()].module.clone(), - resolver: self, - }); + let module = self.expansion_data[&mark.as_u32()].module.clone(); + let mut visitor = ExpansionVisitor { current_module: module, resolver: self }; + visitor.collect_def_ids(mark, expansion); + expansion.visit_with(&mut visitor); } 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> { fn visit_invoc(&mut self, id: ast::NodeId) { - self.resolver.expansion_data.insert(id.as_u32(), ExpansionData { - module: self.current_module.clone(), - }); + self.resolver.expansion_data.get_mut(&id.as_u32()).unwrap().module = + self.current_module.clone(); } // does this attribute list contain "macro_use"? @@ -195,6 +206,22 @@ impl<'a, 'b> ExpansionVisitor<'a, 'b> { 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 {