about summary refs log tree commit diff
path: root/compiler/rustc_resolve/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-11-24 09:17:33 +0000
committerbors <bors@rust-lang.org>2020-11-24 09:17:33 +0000
commit6331023708aabef7fbd4ca502feb48c3afc83b41 (patch)
tree1566cb3d5f96e3bf433107ebb1244176ab8bfb81 /compiler/rustc_resolve/src
parent238994f3b1d6b05ed5c26c1b3af03723a2421700 (diff)
parent27af650a0df2975fba5a8ae3e1a42eada0ff7bd4 (diff)
downloadrust-6331023708aabef7fbd4ca502feb48c3afc83b41.tar.gz
rust-6331023708aabef7fbd4ca502feb48c3afc83b41.zip
Auto merge of #79294 - petrochenkov:determ, r=varkor
resolve: Do not put macros into `module.unexpanded_invocations` unless necessary

Macro invocations in modules <sup>(*)</sup> need to be tracked because they can produce named items when expanded.
We cannot give definite answer to queries like "does this module declare name `n`?" until all macro calls in that module are expanded.

Previously we marked too many macros as potentially producing named items.
E.g. in this example
```rust
mod m {
    const C: u32 = line!();
}
```
`line!()` cannot emit any items into module `m`, but it was still marked.
This PR fixes that and marks macro calls as "unexpanded in module" only if they can actually emit named items into that module.

Diagnostics in UI test outputs have different order now because this change affects macro expansion order.

<sup>*</sup> Any containers for named items are called modules in resolve (that includes blocks, traits and enums in addition to `mod` items).
Diffstat (limited to 'compiler/rustc_resolve/src')
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs29
1 files changed, 20 insertions, 9 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 493b9f15271..6d7e4ebc253 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1155,14 +1155,18 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         false
     }
 
-    fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> {
+    fn visit_invoc(&mut self, id: NodeId) -> ExpnId {
         let invoc_id = id.placeholder_to_expn_id();
-
-        self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
-
         let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
         assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
+        invoc_id
+    }
 
+    /// Visit invocation in context in which it can emit a named item (possibly `macro_rules`)
+    /// directly into its parent scope's module.
+    fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> {
+        let invoc_id = self.visit_invoc(id);
+        self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
         self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
     }
 
@@ -1291,7 +1295,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
                 return;
             }
             ItemKind::MacCall(..) => {
-                self.parent_scope.macro_rules = self.visit_invoc(item.id);
+                self.parent_scope.macro_rules = self.visit_invoc_in_module(item.id);
                 return;
             }
             ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
@@ -1309,7 +1313,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
         if let ast::StmtKind::MacCall(..) = stmt.kind {
-            self.parent_scope.macro_rules = self.visit_invoc(stmt.id);
+            self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id);
         } else {
             visit::walk_stmt(self, stmt);
         }
@@ -1317,7 +1321,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) {
         if let ForeignItemKind::MacCall(_) = foreign_item.kind {
-            self.visit_invoc(foreign_item.id);
+            self.visit_invoc_in_module(foreign_item.id);
             return;
         }
 
@@ -1336,7 +1340,14 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         if let AssocItemKind::MacCall(_) = item.kind {
-            self.visit_invoc(item.id);
+            match ctxt {
+                AssocCtxt::Trait => {
+                    self.visit_invoc_in_module(item.id);
+                }
+                AssocCtxt::Impl => {
+                    self.visit_invoc(item.id);
+                }
+            }
             return;
         }
 
@@ -1460,7 +1471,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
     // type and value namespaces.
     fn visit_variant(&mut self, variant: &'b ast::Variant) {
         if variant.is_placeholder {
-            self.visit_invoc(variant.id);
+            self.visit_invoc_in_module(variant.id);
             return;
         }