Skip to content

Assign def ids and build the module graph during expansion #36601

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 28, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Peform def id assignment during expansion.
  • Loading branch information
jseyfried committed Sep 27, 2016
commit ebaaafcd5d9c71745bfb489e51b074ce00d2e158
86 changes: 56 additions & 30 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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 {
Expand All @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -244,25 +260,28 @@ 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);
self.parent_def = parent_def;
}

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);
}
Expand All @@ -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.
Expand Down
9 changes: 1 addition & 8 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
3 changes: 0 additions & 3 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
16 changes: 13 additions & 3 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
43 changes: 35 additions & 8 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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`.
Expand All @@ -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) {
Expand Down Expand Up @@ -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"?
Expand All @@ -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 {
Expand Down