Skip to content

Commit b54e1e3

Browse files
committed
Differentiate between monotonic and non-monotonic expansion and
only assign node ids during monotonic expansion.
1 parent 78c0039 commit b54e1e3

File tree

5 files changed

+32
-16
lines changed

5 files changed

+32
-16
lines changed

src/libsyntax/ext/base.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,13 @@ impl<'a> ExtCtxt<'a> {
549549

550550
/// Returns a `Folder` for deeply expanding all macros in an AST node.
551551
pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
552-
expand::MacroExpander::new(self, false, false)
552+
expand::MacroExpander::new(self, false)
553+
}
554+
555+
/// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
556+
/// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
557+
pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
558+
expand::MacroExpander::new(self, true)
553559
}
554560

555561
pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree])

src/libsyntax/ext/expand.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,16 @@ pub struct MacroExpander<'a, 'b:'a> {
175175
pub cx: &'a mut ExtCtxt<'b>,
176176
pub single_step: bool,
177177
pub keep_macs: bool,
178+
monotonic: bool, // c.f. `cx.monotonic_expander()`
178179
}
179180

180181
impl<'a, 'b> MacroExpander<'a, 'b> {
181-
pub fn new(cx: &'a mut ExtCtxt<'b>,
182-
single_step: bool,
183-
keep_macs: bool) -> MacroExpander<'a, 'b> {
182+
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
184183
MacroExpander {
185184
cx: cx,
186-
single_step: single_step,
187-
keep_macs: keep_macs
185+
monotonic: monotonic,
186+
single_step: false,
187+
keep_macs: false,
188188
}
189189
}
190190

@@ -245,7 +245,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
245245

246246
self.cx.current_expansion = orig_expansion_data;
247247

248-
let mut placeholder_expander = PlaceholderExpander::new(self.cx);
248+
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
249249
while let Some(expansions) = expansions.pop() {
250250
for (mark, expansion) in expansions.into_iter().rev() {
251251
let expansion = expansion.fold_with(&mut placeholder_expander);
@@ -268,6 +268,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
268268
},
269269
cx: self.cx,
270270
invocations: Vec::new(),
271+
monotonic: self.monotonic,
271272
};
272273
(expansion.fold_with(&mut collector), collector.invocations)
273274
};
@@ -450,6 +451,7 @@ struct InvocationCollector<'a, 'b: 'a> {
450451
cx: &'a mut ExtCtxt<'b>,
451452
cfg: StripUnconfigured<'a>,
452453
invocations: Vec<Invocation>,
454+
monotonic: bool,
453455
}
454456

455457
macro_rules! fully_configure {
@@ -709,8 +711,12 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
709711
}
710712

711713
fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
712-
assert_eq!(id, ast::DUMMY_NODE_ID);
713-
self.cx.resolver.next_node_id()
714+
if self.monotonic {
715+
assert_eq!(id, ast::DUMMY_NODE_ID);
716+
self.cx.resolver.next_node_id()
717+
} else {
718+
id
719+
}
714720
}
715721
}
716722

@@ -763,7 +769,7 @@ pub fn expand_crate(cx: &mut ExtCtxt,
763769
user_exts: Vec<NamedSyntaxExtension>,
764770
c: Crate) -> Crate {
765771
cx.initialize(user_exts, &c);
766-
cx.expander().expand_crate(c)
772+
cx.monotonic_expander().expand_crate(c)
767773
}
768774

769775
// Expands crate using supplied MacroExpander - allows for

src/libsyntax/ext/placeholders.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,15 @@ pub fn macro_scope_placeholder() -> Expansion {
7575
pub struct PlaceholderExpander<'a, 'b: 'a> {
7676
expansions: HashMap<ast::NodeId, Expansion>,
7777
cx: &'a mut ExtCtxt<'b>,
78+
monotonic: bool,
7879
}
7980

8081
impl<'a, 'b> PlaceholderExpander<'a, 'b> {
81-
pub fn new(cx: &'a mut ExtCtxt<'b>) -> Self {
82+
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
8283
PlaceholderExpander {
8384
cx: cx,
8485
expansions: HashMap::new(),
86+
monotonic: monotonic,
8587
}
8688
}
8789

@@ -182,13 +184,15 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
182184
// which shares a HIR node with the expression itself.
183185
ast::StmtKind::Expr(ref expr) if remaining_stmts == 0 => stmt.id = expr.id,
184186

185-
_ => {
187+
_ if self.monotonic => {
186188
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
187189
stmt.id = self.cx.resolver.next_node_id();
188190
}
191+
192+
_ => {}
189193
}
190194

191-
if !macros.is_empty() {
195+
if self.monotonic && !macros.is_empty() {
192196
let macros = mem::replace(&mut macros, Vec::new());
193197
self.cx.resolver.add_expansions_at_stmt(stmt.id, macros);
194198
}

src/libsyntax/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>,
257257
};
258258

259259
let sym = token::gensym_ident("__test_reexports");
260-
let it = cx.ext_cx.expander().fold_item(P(ast::Item {
260+
let it = cx.ext_cx.monotonic_expander().fold_item(P(ast::Item {
261261
ident: sym.clone(),
262262
attrs: Vec::new(),
263263
id: ast::DUMMY_NODE_ID,
@@ -512,7 +512,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
512512
let item_ = ast::ItemKind::Mod(testmod);
513513
let mod_ident = token::gensym_ident("__test");
514514

515-
let mut expander = cx.ext_cx.expander();
515+
let mut expander = cx.ext_cx.monotonic_expander();
516516
let item = expander.fold_item(P(ast::Item {
517517
id: ast::DUMMY_NODE_ID,
518518
ident: mod_ident,

src/libsyntax_ext/rustc_macro_registrar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,5 +273,5 @@ fn mk_registrar(cx: &mut ExtCtxt,
273273
i
274274
});
275275

276-
cx.expander().fold_item(module).pop().unwrap()
276+
cx.monotonic_expander().fold_item(module).pop().unwrap()
277277
}

0 commit comments

Comments
 (0)