Skip to content

Commit

Permalink
resolve: Properly integrate derives and macro_rules scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Aug 17, 2019
1 parent d65e272 commit d479ff2
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
17 changes: 6 additions & 11 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs
Original file line number Diff line number Diff line change
@@ -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()
}
13 changes: 13 additions & 0 deletions src/test/ui/proc-macro/gen-macro-rules.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit d479ff2

Please sign in to comment.