about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-09-14 21:03:09 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-09-27 06:42:10 +0000
commitb3a81ee8448b93182e6f4d2bc6cf327c6af4ecd2 (patch)
tree00c23b561689a5a3f9957c18ae55b48cad41f3dc
parentebaaafcd5d9c71745bfb489e51b074ce00d2e158 (diff)
downloadrust-b3a81ee8448b93182e6f4d2bc6cf327c6af4ecd2.tar.gz
rust-b3a81ee8448b93182e6f4d2bc6cf327c6af4ecd2.zip
Build the reduced graph during expansion.
-rw-r--r--src/librustc_driver/driver.rs13
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs49
-rw-r--r--src/librustc_resolve/lib.rs4
-rw-r--r--src/librustc_resolve/macros.rs21
4 files changed, 61 insertions, 26 deletions
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<T>(&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<Name>,
 
     // Maps the `Mark` of an expansion to its containing module or block.
-    expansion_data: FnvHashMap<u32, macros::ExpansionData>,
+    expansion_data: FnvHashMap<u32, macros::ExpansionData<'a>>,
 }
 
 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<ModuleData>,
     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,
             });
         };