1
Fork 0

expand: Unimplement MutVisitor on MacroExpander

Each call to `fully_expand_fragment` is something unique, interesting, and requiring attention.
It represents a "root" of expansion and its use means that something unusual is happening, like eager expansion or expansion performed outside of the primary expansion pass.
So, it shouldn't be hide under a generic visitor call.

Also, from all the implemented visitor methods only two were actually used.
This commit is contained in:
Vadim Petrochenkov 2019-08-14 02:30:09 +03:00
parent 0d29142aad
commit d416ebeb6e
4 changed files with 31 additions and 33 deletions

View file

@ -947,8 +947,10 @@ pub fn expr_to_spanned_string<'a>(
// Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
expr.span = expr.span.apply_mark(cx.current_expansion.id); expr.span = expr.span.apply_mark(cx.current_expansion.id);
// we want to be able to handle e.g., `concat!("foo", "bar")` // Perform eager expansion on the expression.
cx.expander().visit_expr(&mut expr); // We want to be able to handle e.g., `concat!("foo", "bar")`.
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
Err(match expr.node { Err(match expr.node {
ast::ExprKind::Lit(ref l) => match l.node { ast::ExprKind::Lit(ref l) => match l.node {
ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))),
@ -1013,8 +1015,12 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>,
let mut p = cx.new_parser_from_tts(tts); let mut p = cx.new_parser_from_tts(tts);
let mut es = Vec::new(); let mut es = Vec::new();
while p.token != token::Eof { while p.token != token::Eof {
let mut expr = panictry!(p.parse_expr()); let expr = panictry!(p.parse_expr());
cx.expander().visit_expr(&mut expr);
// Perform eager expansion on the expression.
// We want to be able to handle e.g., `concat!("foo", "bar")`.
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
es.push(expr); es.push(expr);
if p.eat(&token::Comma) { if p.eat(&token::Comma) {
continue; continue;

View file

@ -116,18 +116,6 @@ macro_rules! ast_fragments {
} }
} }
impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> {
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
self.fully_expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr()
}
$($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) {
visit_clobber(ast, |ast| self.fully_expand_fragment(AstFragment::$Kind(ast)).$make_ast());
})?)*
$($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
self.fully_expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast()
})?)*
}
impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> { impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> {
$(fn $make_ast(self: Box<crate::ext::tt::macro_rules::ParserAnyMacro<'a>>) $(fn $make_ast(self: Box<crate::ext::tt::macro_rules::ParserAnyMacro<'a>>)
-> Option<$AstTy> { -> Option<$AstTy> {
@ -286,7 +274,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
} }
// Recursively expand all macro invocations in this AST fragment. // Recursively expand all macro invocations in this AST fragment.
fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let orig_expansion_data = self.cx.current_expansion.clone(); let orig_expansion_data = self.cx.current_expansion.clone();
self.cx.current_expansion.depth = 0; self.cx.current_expansion.depth = 0;

View file

@ -1,18 +1,17 @@
use std::mem; use std::mem;
use smallvec::smallvec;
use syntax::ast::{self, Ident}; use syntax::ast::{self, Ident};
use syntax::attr; use syntax::attr;
use syntax::source_map::{ExpnInfo, ExpnKind, respan}; use syntax::source_map::{ExpnInfo, ExpnKind, respan};
use syntax::ext::base::{ExtCtxt, MacroKind}; use syntax::ext::base::{ExtCtxt, MacroKind};
use syntax::ext::expand::ExpansionConfig; use syntax::ext::expand::{AstFragment, ExpansionConfig};
use syntax::ext::hygiene::ExpnId; use syntax::ext::hygiene::ExpnId;
use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::ext::proc_macro::is_proc_macro_attr;
use syntax::mut_visit::MutVisitor;
use syntax::parse::ParseSess; use syntax::parse::ParseSess;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::symbol::{kw, sym}; use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
struct ProcMacroDerive { struct ProcMacroDerive {
@ -409,5 +408,7 @@ fn mk_decls(
i i
}); });
cx.monotonic_expander().flat_map_item(module).pop().unwrap() // Integrate the new module into existing module structures.
let module = AstFragment::Items(smallvec![module]);
cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap()
} }

View file

@ -6,7 +6,7 @@ use syntax::ast::{self, Ident};
use syntax::attr; use syntax::attr;
use syntax::entry::{self, EntryPointType}; use syntax::entry::{self, EntryPointType};
use syntax::ext::base::{ExtCtxt, Resolver}; use syntax::ext::base::{ExtCtxt, Resolver};
use syntax::ext::expand::ExpansionConfig; use syntax::ext::expand::{AstFragment, ExpansionConfig};
use syntax::ext::hygiene::{ExpnId, MacroKind}; use syntax::ext::hygiene::{ExpnId, MacroKind};
use syntax::feature_gate::Features; use syntax::feature_gate::Features;
use syntax::mut_visit::{*, ExpectOne}; use syntax::mut_visit::{*, ExpectOne};
@ -74,12 +74,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
noop_visit_crate(c, self); noop_visit_crate(c, self);
// Create a main function to run our tests // Create a main function to run our tests
let test_main = { c.module.items.push(mk_main(&mut self.cx));
let unresolved = mk_main(&mut self.cx);
self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap()
};
c.module.items.push(test_main);
} }
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> { fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
@ -216,7 +211,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>,
let name = Ident::from_str("__test_reexports").gensym(); let name = Ident::from_str("__test_reexports").gensym();
let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent); cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent);
let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item { let module = P(ast::Item {
ident: name, ident: name,
attrs: Vec::new(), attrs: Vec::new(),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -224,9 +219,14 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>,
vis: dummy_spanned(ast::VisibilityKind::Public), vis: dummy_spanned(ast::VisibilityKind::Public),
span: DUMMY_SP, span: DUMMY_SP,
tokens: None, tokens: None,
})).pop().unwrap(); });
(it, name) // Integrate the new module into existing module structures.
let module = AstFragment::Items(smallvec![module]);
let module =
cx.ext_cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap();
(module, name)
} }
/// Crawl over the crate, inserting test reexports and the test main function /// Crawl over the crate, inserting test reexports and the test main function
@ -321,7 +321,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
None => Ident::from_str_and_span("main", sp).gensym(), None => Ident::from_str_and_span("main", sp).gensym(),
}; };
P(ast::Item { let main = P(ast::Item {
ident: main_id, ident: main_id,
attrs: vec![main_attr], attrs: vec![main_attr],
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -329,8 +329,11 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
vis: dummy_spanned(ast::VisibilityKind::Public), vis: dummy_spanned(ast::VisibilityKind::Public),
span: sp, span: sp,
tokens: None, tokens: None,
}) });
// Integrate the new item into existing module structures.
let main = AstFragment::Items(smallvec![main]);
cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap()
} }
fn path_name_i(idents: &[Ident]) -> String { fn path_name_i(idents: &[Ident]) -> String {