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.
|
/// 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])
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue