about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-04-16 01:16:43 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-04-16 01:16:43 +0530
commit6a0cfbcac294faab2b8bcd95a04cda042101a2d8 (patch)
tree9960209af7689edfe181a46e2958ccc461e06c92 /src
parentccc7e95a964ece830caf66ad537e89ae6fb397a6 (diff)
parentca1d29c4debb5a58d9c2a9322eea740ca558ade5 (diff)
downloadrust-6a0cfbcac294faab2b8bcd95a04cda042101a2d8.tar.gz
rust-6a0cfbcac294faab2b8bcd95a04cda042101a2d8.zip
Rollup merge of #32923 - jseyfried:fix_hygiene, r=nrc
Fix macro hygiene bug

This fixes #32922 (EDIT: and fixes #31856), macro hygiene bugs.
It is a [breaking-change]. For example, the following would break:
```rust
fn main() {
    let x = true;
    macro_rules! foo { () => {
        let x = 0;
        macro_rules! bar { () => {x} }
        let _: bool = bar!();
        //^ `bar!()` used to resolve the first `x` (a bool),
        //| but will now resolve to the second x (an i32).
    }}
    foo! {};
}
```

r? @nrc
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/ext/expand.rs17
-rw-r--r--src/test/compile-fail/issue-32922.rs41
2 files changed, 50 insertions, 8 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 8550617560d..cd7b0fcfb00 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -504,6 +504,13 @@ pub fn expand_item_mac(it: P<ast::Item>,
 
 /// Expand a stmt
 fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
+    // perform all pending renames
+    let stmt = {
+        let pending_renames = &mut fld.cx.syntax_env.info().pending_renames;
+        let mut rename_fld = IdentRenamer{renames:pending_renames};
+        rename_fld.fold_stmt(stmt).expect_one("rename_fold didn't return one value")
+    };
+
     let (mac, style, attrs) = match stmt.node {
         StmtKind::Mac(mac, style, attrs) => (mac, style, attrs),
         _ => return expand_non_macro_stmt(stmt, fld)
@@ -717,14 +724,8 @@ pub fn expand_block(blk: P<Block>, fld: &mut MacroExpander) -> P<Block> {
 pub fn expand_block_elts(b: P<Block>, fld: &mut MacroExpander) -> P<Block> {
     b.map(|Block {id, stmts, expr, rules, span}| {
         let new_stmts = stmts.into_iter().flat_map(|x| {
-            // perform all pending renames
-            let renamed_stmt = {
-                let pending_renames = &mut fld.cx.syntax_env.info().pending_renames;
-                let mut rename_fld = IdentRenamer{renames:pending_renames};
-                rename_fld.fold_stmt(x).expect_one("rename_fold didn't return one value")
-            };
-            // expand macros in the statement
-            fld.fold_stmt(renamed_stmt).into_iter()
+            // perform pending renames and expand macros in the statement
+            fld.fold_stmt(x).into_iter()
         }).collect();
         let new_expr = expr.map(|x| {
             let expr = {
diff --git a/src/test/compile-fail/issue-32922.rs b/src/test/compile-fail/issue-32922.rs
new file mode 100644
index 00000000000..491c087c101
--- /dev/null
+++ b/src/test/compile-fail/issue-32922.rs
@@ -0,0 +1,41 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+macro_rules! foo { () => {
+    let x = 1;
+    macro_rules! bar { () => {x} }
+    let _ = bar!();
+}}
+
+macro_rules! bar { // test issue #31856
+    ($n:ident) => (
+        let a = 1;
+        let $n = a;
+    )
+}
+
+macro_rules! baz {
+    ($i:ident) => {
+        let mut $i = 2;
+        $i = $i + 1;
+    }
+}
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+    foo! {};
+    bar! {};
+
+    let mut a = true;
+    baz!(a);
+}