about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/map/def_collector.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs17
-rw-r--r--src/librustc_resolve/macros.rs17
-rw-r--r--src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs12
-rw-r--r--src/test/ui/proc-macro/gen-macro-rules.rs13
5 files changed, 47 insertions, 14 deletions
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index df9bd3a35a6..d725afa4052 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -74,7 +74,7 @@ impl<'a> DefCollector<'a> {
         })
     }
 
-    fn visit_macro_invoc(&mut self, id: NodeId) {
+    pub fn visit_macro_invoc(&mut self, id: NodeId) {
         self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def);
     }
 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 1510d74babb..fe5c85d3a95 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -161,11 +161,24 @@ impl<'a> Resolver<'a> {
     }
 
     crate fn build_reduced_graph(
-        &mut self, fragment: &AstFragment, parent_scope: ParentScope<'a>
+        &mut self,
+        fragment: &AstFragment,
+        extra_placeholders: &[ExpnId],
+        parent_scope: ParentScope<'a>,
     ) -> LegacyScope<'a> {
-        fragment.visit_with(&mut DefCollector::new(&mut self.definitions, parent_scope.expansion));
+        let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion);
+        fragment.visit_with(&mut def_collector);
+        for placeholder in extra_placeholders {
+            def_collector.visit_macro_invoc(NodeId::placeholder_from_expn_id(*placeholder));
+        }
+
         let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
         fragment.visit_with(&mut visitor);
+        for placeholder in extra_placeholders {
+            visitor.parent_scope.legacy =
+                visitor.visit_invoc(NodeId::placeholder_from_expn_id(*placeholder));
+        }
+
         visitor.parent_scope.legacy
     }
 
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 6f49377c187..ff0c14f9cd9 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -115,23 +115,18 @@ impl<'a> base::Resolver for Resolver<'a> {
         });
     }
 
+
+
     fn visit_ast_fragment_with_placeholders(
         &mut self, expansion: ExpnId, fragment: &AstFragment, derives: &[ExpnId]
     ) {
-        // Fill in some data for derives if the fragment is from a derive container.
+        // Integrate the new AST fragment into all the definition and module structures.
         // We are inside the `expansion` now, but other parent scope components are still the same.
         let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
-        let parent_def = self.definitions.invocation_parent(expansion);
-        self.invocation_parent_scopes.extend(derives.iter().map(|&derive| (derive, parent_scope)));
-        for &derive_invoc_id in derives {
-            self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
-        }
-        parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion);
-        parent_scope.module.unresolved_invocations.borrow_mut().extend(derives);
-
-        // Integrate the new AST fragment into all the definition and module structures.
-        let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope);
+        let output_legacy_scope = self.build_reduced_graph(fragment, derives, parent_scope);
         self.output_legacy_scopes.insert(expansion, output_legacy_scope);
+
+        parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion);
     }
 
     fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) {
diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs
new file mode 100644
index 00000000000..d4b67d6b0b0
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(repro)]
+pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream {
+    "macro_rules! m {()=>{}}".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/gen-macro-rules.rs b/src/test/ui/proc-macro/gen-macro-rules.rs
new file mode 100644
index 00000000000..13ad27f9372
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-macro-rules.rs
@@ -0,0 +1,13 @@
+// Derive macros can generate `macro_rules` items, regression test for issue #63651.
+
+// check-pass
+// aux-build:gen-macro-rules.rs
+
+extern crate gen_macro_rules as repro;
+
+#[derive(repro::repro)]
+pub struct S;
+
+m!(); // OK
+
+fn main() {}