resolve: Properly integrate derives and macro_rules
scopes
This commit is contained in:
parent
d65e272a9f
commit
d479ff2ffe
5 changed files with 47 additions and 14 deletions
|
@ -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);
|
self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,11 +161,24 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn build_reduced_graph(
|
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> {
|
) -> 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 };
|
let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
|
||||||
fragment.visit_with(&mut visitor);
|
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
|
visitor.parent_scope.legacy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,23 +115,18 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn visit_ast_fragment_with_placeholders(
|
fn visit_ast_fragment_with_placeholders(
|
||||||
&mut self, expansion: ExpnId, fragment: &AstFragment, derives: &[ExpnId]
|
&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.
|
// 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_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
|
||||||
let parent_def = self.definitions.invocation_parent(expansion);
|
let output_legacy_scope = self.build_reduced_graph(fragment, derives, parent_scope);
|
||||||
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);
|
|
||||||
self.output_legacy_scopes.insert(expansion, output_legacy_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) {
|
fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) {
|
||||||
|
|
12
src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs
Normal file
12
src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs
Normal file
|
@ -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
src/test/ui/proc-macro/gen-macro-rules.rs
Normal file
13
src/test/ui/proc-macro/gen-macro-rules.rs
Normal file
|
@ -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() {}
|
Loading…
Add table
Add a link
Reference in a new issue