1
Fork 0

Differentiate between monotonic and non-monotonic expansion and

only assign node ids during monotonic expansion.
This commit is contained in:
Jeffrey Seyfried 2016-09-06 05:42:45 +00:00
parent 78c0039878
commit b54e1e3997
5 changed files with 32 additions and 16 deletions

View file

@ -549,7 +549,13 @@ impl<'a> ExtCtxt<'a> {
/// Returns a `Folder` for deeply expanding all macros in an AST node.
pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
expand::MacroExpander::new(self, false, false)
expand::MacroExpander::new(self, false)
}
/// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
/// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
expand::MacroExpander::new(self, true)
}
pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree])

View file

@ -175,16 +175,16 @@ pub struct MacroExpander<'a, 'b:'a> {
pub cx: &'a mut ExtCtxt<'b>,
pub single_step: bool,
pub keep_macs: bool,
monotonic: bool, // c.f. `cx.monotonic_expander()`
}
impl<'a, 'b> MacroExpander<'a, 'b> {
pub fn new(cx: &'a mut ExtCtxt<'b>,
single_step: bool,
keep_macs: bool) -> MacroExpander<'a, 'b> {
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
MacroExpander {
cx: cx,
single_step: single_step,
keep_macs: keep_macs
monotonic: monotonic,
single_step: false,
keep_macs: false,
}
}
@ -245,7 +245,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.cx.current_expansion = orig_expansion_data;
let mut placeholder_expander = PlaceholderExpander::new(self.cx);
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
while let Some(expansions) = expansions.pop() {
for (mark, expansion) in expansions.into_iter().rev() {
let expansion = expansion.fold_with(&mut placeholder_expander);
@ -268,6 +268,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
},
cx: self.cx,
invocations: Vec::new(),
monotonic: self.monotonic,
};
(expansion.fold_with(&mut collector), collector.invocations)
};
@ -450,6 +451,7 @@ struct InvocationCollector<'a, 'b: 'a> {
cx: &'a mut ExtCtxt<'b>,
cfg: StripUnconfigured<'a>,
invocations: Vec<Invocation>,
monotonic: bool,
}
macro_rules! fully_configure {
@ -709,8 +711,12 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
}
fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
if self.monotonic {
assert_eq!(id, ast::DUMMY_NODE_ID);
self.cx.resolver.next_node_id()
} else {
id
}
}
}
@ -763,7 +769,7 @@ pub fn expand_crate(cx: &mut ExtCtxt,
user_exts: Vec<NamedSyntaxExtension>,
c: Crate) -> Crate {
cx.initialize(user_exts, &c);
cx.expander().expand_crate(c)
cx.monotonic_expander().expand_crate(c)
}
// Expands crate using supplied MacroExpander - allows for

View file

@ -75,13 +75,15 @@ pub fn macro_scope_placeholder() -> Expansion {
pub struct PlaceholderExpander<'a, 'b: 'a> {
expansions: HashMap<ast::NodeId, Expansion>,
cx: &'a mut ExtCtxt<'b>,
monotonic: bool,
}
impl<'a, 'b> PlaceholderExpander<'a, 'b> {
pub fn new(cx: &'a mut ExtCtxt<'b>) -> Self {
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
PlaceholderExpander {
cx: cx,
expansions: HashMap::new(),
monotonic: monotonic,
}
}
@ -182,13 +184,15 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
// which shares a HIR node with the expression itself.
ast::StmtKind::Expr(ref expr) if remaining_stmts == 0 => stmt.id = expr.id,
_ => {
_ if self.monotonic => {
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
stmt.id = self.cx.resolver.next_node_id();
}
_ => {}
}
if !macros.is_empty() {
if self.monotonic && !macros.is_empty() {
let macros = mem::replace(&mut macros, Vec::new());
self.cx.resolver.add_expansions_at_stmt(stmt.id, macros);
}

View file

@ -257,7 +257,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>,
};
let sym = token::gensym_ident("__test_reexports");
let it = cx.ext_cx.expander().fold_item(P(ast::Item {
let it = cx.ext_cx.monotonic_expander().fold_item(P(ast::Item {
ident: sym.clone(),
attrs: Vec::new(),
id: ast::DUMMY_NODE_ID,
@ -512,7 +512,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
let item_ = ast::ItemKind::Mod(testmod);
let mod_ident = token::gensym_ident("__test");
let mut expander = cx.ext_cx.expander();
let mut expander = cx.ext_cx.monotonic_expander();
let item = expander.fold_item(P(ast::Item {
id: ast::DUMMY_NODE_ID,
ident: mod_ident,

View file

@ -273,5 +273,5 @@ fn mk_registrar(cx: &mut ExtCtxt,
i
});
cx.expander().fold_item(module).pop().unwrap()
cx.monotonic_expander().fold_item(module).pop().unwrap()
}