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. /// Returns a `Folder` for deeply expanding all macros in an AST node.
pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { 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]) 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 cx: &'a mut ExtCtxt<'b>,
pub single_step: bool, pub single_step: bool,
pub keep_macs: bool, pub keep_macs: bool,
monotonic: bool, // c.f. `cx.monotonic_expander()`
} }
impl<'a, 'b> MacroExpander<'a, 'b> { impl<'a, 'b> MacroExpander<'a, 'b> {
pub fn new(cx: &'a mut ExtCtxt<'b>, pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
single_step: bool,
keep_macs: bool) -> MacroExpander<'a, 'b> {
MacroExpander { MacroExpander {
cx: cx, cx: cx,
single_step: single_step, monotonic: monotonic,
keep_macs: keep_macs single_step: false,
keep_macs: false,
} }
} }
@ -245,7 +245,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.cx.current_expansion = orig_expansion_data; 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() { while let Some(expansions) = expansions.pop() {
for (mark, expansion) in expansions.into_iter().rev() { for (mark, expansion) in expansions.into_iter().rev() {
let expansion = expansion.fold_with(&mut placeholder_expander); let expansion = expansion.fold_with(&mut placeholder_expander);
@ -268,6 +268,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
}, },
cx: self.cx, cx: self.cx,
invocations: Vec::new(), invocations: Vec::new(),
monotonic: self.monotonic,
}; };
(expansion.fold_with(&mut collector), collector.invocations) (expansion.fold_with(&mut collector), collector.invocations)
}; };
@ -450,6 +451,7 @@ struct InvocationCollector<'a, 'b: 'a> {
cx: &'a mut ExtCtxt<'b>, cx: &'a mut ExtCtxt<'b>,
cfg: StripUnconfigured<'a>, cfg: StripUnconfigured<'a>,
invocations: Vec<Invocation>, invocations: Vec<Invocation>,
monotonic: bool,
} }
macro_rules! fully_configure { 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 { fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
if self.monotonic {
assert_eq!(id, ast::DUMMY_NODE_ID); assert_eq!(id, ast::DUMMY_NODE_ID);
self.cx.resolver.next_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>, user_exts: Vec<NamedSyntaxExtension>,
c: Crate) -> Crate { c: Crate) -> Crate {
cx.initialize(user_exts, &c); cx.initialize(user_exts, &c);
cx.expander().expand_crate(c) cx.monotonic_expander().expand_crate(c)
} }
// Expands crate using supplied MacroExpander - allows for // 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> { pub struct PlaceholderExpander<'a, 'b: 'a> {
expansions: HashMap<ast::NodeId, Expansion>, expansions: HashMap<ast::NodeId, Expansion>,
cx: &'a mut ExtCtxt<'b>, cx: &'a mut ExtCtxt<'b>,
monotonic: bool,
} }
impl<'a, 'b> PlaceholderExpander<'a, 'b> { 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 { PlaceholderExpander {
cx: cx, cx: cx,
expansions: HashMap::new(), 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. // which shares a HIR node with the expression itself.
ast::StmtKind::Expr(ref expr) if remaining_stmts == 0 => stmt.id = expr.id, ast::StmtKind::Expr(ref expr) if remaining_stmts == 0 => stmt.id = expr.id,
_ => { _ if self.monotonic => {
assert_eq!(stmt.id, ast::DUMMY_NODE_ID); assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
stmt.id = self.cx.resolver.next_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()); let macros = mem::replace(&mut macros, Vec::new());
self.cx.resolver.add_expansions_at_stmt(stmt.id, macros); 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 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(), ident: sym.clone(),
attrs: Vec::new(), attrs: Vec::new(),
id: ast::DUMMY_NODE_ID, 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 item_ = ast::ItemKind::Mod(testmod);
let mod_ident = token::gensym_ident("__test"); 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 { let item = expander.fold_item(P(ast::Item {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
ident: mod_ident, ident: mod_ident,

View file

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