Skip to content

Commit

Permalink
Differentiate between monotonic and non-monotonic expansion and
Browse files Browse the repository at this point in the history
only assign node ids during monotonic expansion.
  • Loading branch information
jseyfried committed Sep 13, 2016
1 parent 78c0039 commit b54e1e3
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 16 deletions.
8 changes: 7 additions & 1 deletion src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
24 changes: 15 additions & 9 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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);
Expand All @@ -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)
};
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
}
}

Expand Down Expand Up @@ -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
Expand Down
10 changes: 7 additions & 3 deletions src/libsyntax/ext/placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_ext/rustc_macro_registrar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}

0 comments on commit b54e1e3

Please sign in to comment.