Differentiate between monotonic and non-monotonic expansion and
only assign node ids during monotonic expansion.
This commit is contained in:
parent
78c0039878
commit
b54e1e3997
5 changed files with 32 additions and 16 deletions
|
@ -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])
|
||||
|
|
|
@ -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 {
|
||||
assert_eq!(id, ast::DUMMY_NODE_ID);
|
||||
self.cx.resolver.next_node_id()
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue