diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3629e668fa9..09beda33483 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -559,7 +559,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.force_mode = orig_force_mode; // Finally incorporate all the expanded macros into the input AST fragment. - let mut placeholder_expander = PlaceholderExpander::default(); + let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { placeholder_expander @@ -1341,9 +1341,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } + // The placeholder expander gives ids to statements, so we avoid folding the id here. // We don't use `assign_id!` - it will be called when we visit statement's contents // (e.g. an expression, item, or local) - let res = noop_flat_map_stmt(stmt, self); + let ast::Stmt { id, kind, span } = stmt; + let res = noop_flat_map_stmt_kind(kind, self) + .into_iter() + .map(|kind| ast::Stmt { id, kind, span }) + .collect(); self.cx.current_expansion.is_trailing_mac = false; res diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 43287984050..efed41de23a 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -7,7 +7,6 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] -#![recursion_limit = "256"] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 8e78fcbb8db..6586ba138fb 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -1,3 +1,4 @@ +use crate::base::ExtCtxt; use crate::expand::{AstFragment, AstFragmentKind}; use rustc_ast as ast; @@ -174,12 +175,17 @@ pub fn placeholder( } } -#[derive(Default)] -pub struct PlaceholderExpander { +pub struct PlaceholderExpander<'a, 'b> { expanded_fragments: FxHashMap, + cx: &'a mut ExtCtxt<'b>, + monotonic: bool, } -impl PlaceholderExpander { +impl<'a, 'b> PlaceholderExpander<'a, 'b> { + pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { + PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic } + } + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); @@ -190,7 +196,7 @@ impl PlaceholderExpander { } } -impl MutVisitor for PlaceholderExpander { +impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { if arm.is_placeholder { self.remove(arm.id).make_arms() @@ -354,4 +360,15 @@ impl MutVisitor for PlaceholderExpander { _ => noop_visit_ty(ty, self), } } + + fn visit_block(&mut self, block: &mut P) { + noop_visit_block(block, self); + + for stmt in block.stmts.iter_mut() { + if self.monotonic { + assert_eq!(stmt.id, ast::DUMMY_NODE_ID); + stmt.id = self.cx.resolver.next_node_id(); + } + } + } }