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:
parent
0d29142aad
commit
d416ebeb6e
4 changed files with 31 additions and 33 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue