Skip to content
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

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

Merged
merged 7 commits into from
Sep 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
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
115 changes: 75 additions & 40 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,39 @@ 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(MacroInvocationData)>,
}

impl<'ast> DefCollector<'ast> {
pub fn new(definitions: &'ast mut Definitions) -> DefCollector<'ast> {
pub struct MacroInvocationData {
pub id: NodeId,
pub def_index: DefIndex,
pub const_integer: bool,
}

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 +73,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,29 +92,28 @@ 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);
self.parent_def = parent;
}

fn visit_ast_const_integer(&mut self, expr: &Expr) {
// Find the node which will be used after lowering.
if let ExprKind::Paren(ref inner) = expr.node {
return self.visit_ast_const_integer(inner);
}

// FIXME(eddyb) Closures should have separate
// function definition IDs and expression IDs.
if let ExprKind::Closure(..) = expr.node {
return;
pub fn visit_ast_const_integer(&mut self, expr: &Expr) {
match expr.node {
// Find the node which will be used after lowering.
ExprKind::Paren(ref inner) => return self.visit_ast_const_integer(inner),
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true),
// FIXME(eddyb) Closures should have separate
// function definition IDs and expression IDs.
ExprKind::Closure(..) => return,
_ => {}
}

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 +122,19 @@ impl<'ast> DefCollector<'ast> {

self.create_def(expr.id, DefPathData::Initializer);
}

fn visit_macro_invoc(&mut self, id: NodeId, const_integer: bool) {
if let Some(ref mut visit) = self.visit_macro_invoc {
visit(MacroInvocationData {
id: id,
const_integer: const_integer,
def_index: 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 +146,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, false),
ItemKind::Use(..) => DefPathData::Misc,
};
let def = self.create_def(i.id, def_data);
Expand Down Expand Up @@ -198,7 +219,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, false),
};

let def = self.create_def(ti.id, def_data);
Expand All @@ -216,7 +237,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, false),
};

let def = self.create_def(ii.id, def_data);
Expand All @@ -232,9 +253,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, false),
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 +269,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, false),
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, false),
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 +302,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, false),
_ => 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, MacroInvocationData};
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
DisambiguatedDefPathData, InlinedRootPath};

Expand Down
16 changes: 6 additions & 10 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,12 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
}
sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?;

// Currently, we ignore the name resolution data structures for the purposes of dependency
// tracking. Instead we will run name resolution and include its output in the hash of each
// item, much like we do for macro expansion. In other words, the hash reflects not just
// its contents but the results of name resolution on those contents. Hopefully we'll push
// this back at some point.
let _ignore = sess.dep_graph.in_ignore();
let mut crate_loader = CrateLoader::new(sess, &cstore, &krate, crate_name);
let resolver_arenas = Resolver::arenas();
let mut resolver =
Expand Down Expand Up @@ -733,9 +739,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 All @@ -745,13 +748,6 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
|| ast_validation::check_crate(sess, &krate));

time(sess.time_passes(), "name resolution", || -> CompileResult {
// Currently, we ignore the name resolution data structures for the purposes of dependency
// tracking. Instead we will run name resolution and include its output in the hash of each
// item, much like we do for macro expansion. In other words, the hash reflects not just
// its contents but the results of name resolution on those contents. Hopefully we'll push
// this back at some point.
let _ignore = sess.dep_graph.in_ignore();
resolver.build_reduced_graph(&krate);
resolver.resolve_imports();

// Since import resolution will eventually happen in expansion,
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_metadata/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ Erroneous code examples:

```compile_fail,E0466
#[macro_use(a_macro(another_macro))] // error: invalid import declaration
extern crate some_crate;
extern crate core as some_crate;

#[macro_use(i_want = "some_macros")] // error: invalid import declaration
extern crate another_crate;
extern crate core as another_crate;
```

This is a syntax error at the level of attribute declarations. The proper
Expand Down Expand Up @@ -135,10 +135,10 @@ Erroneous code examples:

```compile_fail,E0467
#[macro_reexport] // error: no macros listed for export
extern crate macros_for_good;
extern crate core as macros_for_good;

#[macro_reexport(fun_macro = "foo")] // error: not a macro identifier
extern crate other_macros_for_good;
extern crate core as other_macros_for_good;
```

This is a syntax error at the level of attribute declarations.
Expand All @@ -165,8 +165,8 @@ Example of erroneous code:
```compile_fail,E0468
mod foo {
#[macro_use(helpful_macro)] // error: must be at crate root to import
extern crate some_crate; // macros from another crate
helpful_macro!(...)
extern crate core; // macros from another crate
helpful_macro!(...);
}
```

Expand Down
Loading