diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 226eb545d2c..f9ac1312d3c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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 = @@ -742,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, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9202f8c0946..a196e664b73 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -31,8 +31,7 @@ use syntax::ast::Name; use syntax::attr; use syntax::parse::token; -use syntax::ast::{Block, Crate}; -use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind}; +use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::parse::token::keywords; @@ -53,11 +52,6 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) { } impl<'b> Resolver<'b> { - /// Constructs the reduced graph for the entire crate. - pub fn build_reduced_graph(&mut self, krate: &Crate) { - visit::walk_crate(&mut BuildReducedGraphVisitor { resolver: self }, krate); - } - /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. fn define(&mut self, parent: Module<'b>, name: Name, ns: Namespace, def: T) @@ -72,7 +66,7 @@ impl<'b> Resolver<'b> { fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { // If any statements are items, we need to create an anonymous module block.stmts.iter().any(|statement| match statement.node { - StmtKind::Item(_) => true, + StmtKind::Item(_) | StmtKind::Mac(_) => true, _ => false, }) } @@ -206,6 +200,8 @@ impl<'b> Resolver<'b> { } } + ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root + ItemKind::Mod(..) => { let def = Def::Mod(self.definitions.local_def_id(item.id)); let module = self.arenas.alloc_module(ModuleS { @@ -478,12 +474,42 @@ impl<'b> Resolver<'b> { } } -struct BuildReducedGraphVisitor<'a, 'b: 'a> { - resolver: &'a mut Resolver<'b>, +pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { + pub resolver: &'a mut Resolver<'b>, +} + +impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { + fn visit_invoc(&mut self, id: ast::NodeId) { + self.resolver.expansion_data.get_mut(&id.as_u32()).unwrap().module2 = + self.resolver.current_module; + } +} + +macro_rules! method { + ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => { + fn $visit(&mut self, node: &$ty) { + match node.node { + $invoc(..) => self.visit_invoc(node.id), + _ => visit::$walk(self, node), + } + } + } } impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { + method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); + method!(visit_stmt: ast::Stmt, ast::StmtKind::Mac, walk_stmt); + method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); + method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); + method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty); + fn visit_item(&mut self, item: &Item) { + match item.node { + ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder + ItemKind::Mac(..) => return self.visit_invoc(item.id), + _ => {} + } + let parent = self.resolver.current_module; self.resolver.build_reduced_graph_for_item(item); visit::walk_item(self, item); @@ -492,6 +518,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { self.resolver.build_reduced_graph_for_foreign_item(foreign_item); + visit::walk_foreign_item(self, foreign_item); } fn visit_block(&mut self, block: &Block) { @@ -515,7 +542,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { (Def::Method(item_def_id), ValueNS) } TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS), - TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), + TraitItemKind::Macro(_) => return self.visit_invoc(item.id), }; self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 467967a4f33..82fa5e4b3c6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1074,7 +1074,7 @@ pub struct Resolver<'a> { macro_names: FnvHashSet, // Maps the `Mark` of an expansion to its containing module or block. - expansion_data: FnvHashMap, + expansion_data: FnvHashMap>, } pub struct ResolverArenas<'a> { @@ -1192,7 +1192,7 @@ impl<'a> Resolver<'a> { DefCollector::new(&mut definitions).collect_root(); let mut expansion_data = FnvHashMap(); - expansion_data.insert(0, macros::ExpansionData::root()); // Crate root expansion + expansion_data.insert(0, macros::ExpansionData::root(graph_root)); // Crate root expansion Resolver { session: session, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ebfdc32fabd..20b10177012 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Resolver; +use {Module, Resolver}; +use build_reduced_graph::BuildReducedGraphVisitor; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefIndex}; use rustc::hir::map::DefCollector; use rustc::middle::cstore::LoadedMacro; @@ -30,16 +31,18 @@ use syntax::visit::{self, Visitor}; use syntax_pos::Span; #[derive(Clone)] -pub struct ExpansionData { +pub struct ExpansionData<'a> { module: Rc, def_index: DefIndex, + pub module2: Module<'a>, } -impl ExpansionData { - pub fn root() -> Self { +impl<'a> ExpansionData<'a> { + pub fn root(graph_root: Module<'a>) -> Self { ExpansionData { module: Default::default(), def_index: CRATE_DEF_INDEX, + module2: graph_root, } } } @@ -58,10 +61,14 @@ impl<'a> base::Resolver for Resolver<'a> { } fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) { - let module = self.expansion_data[&mark.as_u32()].module.clone(); - let mut visitor = ExpansionVisitor { current_module: module, resolver: self }; + let expansion_data = self.expansion_data[&mark.as_u32()].clone(); + self.current_module = expansion_data.module2; + let mut visitor = + ExpansionVisitor { current_module: expansion_data.module, resolver: self }; + visitor.collect_def_ids(mark, expansion); expansion.visit_with(&mut visitor); + expansion.visit_with(&mut BuildReducedGraphVisitor { resolver: visitor.resolver }); } fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { @@ -210,11 +217,13 @@ impl<'a, 'b> ExpansionVisitor<'a, 'b> { fn collect_def_ids(&mut self, mark: Mark, expansion: &Expansion) { let expansion_data = &mut self.resolver.expansion_data; let module = &self.current_module; + let module2 = self.resolver.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(), + module2: module2, }); };