From d479ff2ffe75e966fc802505852b1c74f1da95df Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 17 Aug 2019 19:32:52 +0300 Subject: [PATCH] resolve: Properly integrate derives and `macro_rules` scopes --- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 17 +++++++++++++++-- src/librustc_resolve/macros.rs | 17 ++++++----------- .../ui/proc-macro/auxiliary/gen-macro-rules.rs | 12 ++++++++++++ src/test/ui/proc-macro/gen-macro-rules.rs | 13 +++++++++++++ 5 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs create mode 100644 src/test/ui/proc-macro/gen-macro-rules.rs 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() {}