about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-11-14 09:18:10 -0800
committerJorge Aparicio <japaricious@gmail.com>2014-12-18 12:09:07 -0500
commitddb2466f6a1bb66f22824334022a4cee61c73bdc (patch)
tree9cb97d3e4c4521b56d0776e5f7bda81e62135be4 /src/libsyntax/ext
parentc0b2885ee12b79c99ac8245edb6eebaaa8e7fef1 (diff)
downloadrust-ddb2466f6a1bb66f22824334022a4cee61c73bdc.tar.gz
rust-ddb2466f6a1bb66f22824334022a4cee61c73bdc.zip
librustc: Always parse `macro!()`/`macro![]` as expressions if not
followed by a semicolon.

This allows code like `vec![1i, 2, 3].len();` to work.

This breaks code that uses macros as statements without putting
semicolons after them, such as:

    fn main() {
        ...
        assert!(a == b)
        assert!(c == d)
        println(...);
    }

It also breaks code that uses macros as items without semicolons:

    local_data_key!(foo)

    fn main() {
        println("hello world")
    }

Add semicolons to fix this code. Those two examples can be fixed as
follows:

    fn main() {
        ...
        assert!(a == b);
        assert!(c == d);
        println(...);
    }

    local_data_key!(foo);

    fn main() {
        println("hello world")
    }

RFC #378.

Closes #18635.

[breaking-change]
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/expand.rs63
-rw-r--r--src/libsyntax/ext/mtwt.rs4
-rw-r--r--src/libsyntax/ext/quote.rs122
3 files changed, 95 insertions, 94 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index e280e6e4491..20c8ff20b71 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -11,7 +11,8 @@ use self::Either::*;
 
 use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
 use ast::{Local, Ident, MacInvocTT};
-use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi};
+use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
+use ast::{StmtExpr, StmtSemi};
 use ast::TokenTree;
 use ast;
 use ext::mtwt;
@@ -354,7 +355,7 @@ fn expand_loop_block(loop_block: P<Block>,
 
 // eval $e with a new exts frame.
 // must be a macro so that $e isn't evaluated too early.
-macro_rules! with_exts_frame (
+macro_rules! with_exts_frame {
     ($extsboxexpr:expr,$macros_escape:expr,$e:expr) =>
     ({$extsboxexpr.push_frame();
       $extsboxexpr.info().macros_escape = $macros_escape;
@@ -362,7 +363,7 @@ macro_rules! with_exts_frame (
       $extsboxexpr.pop_frame();
       result
      })
-)
+}
 
 // When we enter a module, record it, for the sake of `module!`
 pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
@@ -636,8 +637,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
 // I don't understand why this returns a vector... it looks like we're
 // half done adding machinery to allow macros to expand into multiple statements.
 fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> {
-    let (mac, semi) = match s.node {
-        StmtMac(mac, semi) => (mac, semi),
+    let (mac, style) = match s.node {
+        StmtMac(mac, style) => (mac, style),
         _ => return expand_non_macro_stmt(s, fld)
     };
     let expanded_stmt = match expand_mac_invoc(mac, s.span,
@@ -653,7 +654,7 @@ fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> {
     let fully_expanded = fld.fold_stmt(expanded_stmt);
     fld.cx.bt_pop();
 
-    if semi {
+    if style == MacStmtWithSemicolon {
         fully_expanded.into_iter().map(|s| s.map(|Spanned {node, span}| {
             Spanned {
                 node: match node {
@@ -1324,7 +1325,7 @@ mod test {
     // make sure that macros can't escape fns
     #[should_fail]
     #[test] fn macros_cant_escape_fns_test () {
-        let src = "fn bogus() {macro_rules! z (() => (3+4))}\
+        let src = "fn bogus() {macro_rules! z (() => (3+4));}\
                    fn inty() -> int { z!() }".to_string();
         let sess = parse::new_parse_sess();
         let crate_ast = parse::parse_crate_from_source_str(
@@ -1338,7 +1339,7 @@ mod test {
     // make sure that macros can't escape modules
     #[should_fail]
     #[test] fn macros_cant_escape_mods_test () {
-        let src = "mod foo {macro_rules! z (() => (3+4))}\
+        let src = "mod foo {macro_rules! z (() => (3+4));}\
                    fn inty() -> int { z!() }".to_string();
         let sess = parse::new_parse_sess();
         let crate_ast = parse::parse_crate_from_source_str(
@@ -1350,7 +1351,7 @@ mod test {
 
     // macro_escape modules should allow macros to escape
     #[test] fn macros_can_escape_flattened_mods_test () {
-        let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\
+        let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\
                    fn inty() -> int { z!() }".to_string();
         let sess = parse::new_parse_sess();
         let crate_ast = parse::parse_crate_from_source_str(
@@ -1402,13 +1403,13 @@ mod test {
 
     #[test] fn macro_tokens_should_match(){
         expand_crate_str(
-            "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_string());
+            "macro_rules! m((a)=>(13)) ;fn main(){m!(a);}".to_string());
     }
 
     // should be able to use a bound identifier as a literal in a macro definition:
     #[test] fn self_macro_parsing(){
         expand_crate_str(
-            "macro_rules! foo ((zz) => (287u;))
+            "macro_rules! foo ((zz) => (287u;));
             fn f(zz : int) {foo!(zz);}".to_string()
             );
     }
@@ -1451,16 +1452,16 @@ mod test {
                 ("fn main () {let x: int = 13;x;}",
                  vec!(vec!(0)), false),
                 // the use of b after the + should be renamed, the other one not:
-                ("macro_rules! f (($x:ident) => (b + $x)) fn a() -> int { let b = 13; f!(b)}",
+                ("macro_rules! f (($x:ident) => (b + $x)); fn a() -> int { let b = 13; f!(b)}",
                  vec!(vec!(1)), false),
                 // the b before the plus should not be renamed (requires marks)
-                ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}",
+                ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> int { f!(b)}",
                  vec!(vec!(1)), false),
                 // the marks going in and out of letty should cancel, allowing that $x to
                 // capture the one following the semicolon.
                 // this was an awesome test case, and caught a *lot* of bugs.
-                ("macro_rules! letty(($x:ident) => (let $x = 15;))
-                  macro_rules! user(($x:ident) => ({letty!($x); $x}))
+                ("macro_rules! letty(($x:ident) => (let $x = 15;));
+                  macro_rules! user(($x:ident) => ({letty!($x); $x}));
                   fn main() -> int {user!(z)}",
                  vec!(vec!(0)), false)
                 );
@@ -1488,7 +1489,7 @@ mod test {
     #[test] fn issue_6994(){
         run_renaming_test(
             &("macro_rules! g (($x:ident) =>
-              ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)}))
+              ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)}));
               fn a(){g!(z)}",
               vec!(vec!(0)),false),
             0)
@@ -1498,7 +1499,7 @@ mod test {
     // fn z() {match 8 {x_1 => {match 9 {x_2 | x_2 if x_2 == x_1 => x_2 + x_1}}}}
     #[test] fn issue_9384(){
         run_renaming_test(
-            &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}}))
+            &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}}));
               fn z() {match 8 {x => bad_macro!(x)}}",
               // NB: the third "binding" is the repeat of the second one.
               vec!(vec!(1,3),vec!(0,2),vec!(0,2)),
@@ -1511,8 +1512,8 @@ mod test {
     // fn main(){let g1_1 = 13; g1_1}}
     #[test] fn pat_expand_issue_15221(){
         run_renaming_test(
-            &("macro_rules! inner ( ($e:pat ) => ($e))
-              macro_rules! outer ( ($e:pat ) => (inner!($e)))
+            &("macro_rules! inner ( ($e:pat ) => ($e));
+              macro_rules! outer ( ($e:pat ) => (inner!($e)));
               fn main() { let outer!(g) = 13; g;}",
               vec!(vec!(0)),
               true),
@@ -1527,8 +1528,8 @@ mod test {
     // method expands to fn get_x(&self_0, x_1:int) {self_0 + self_2 + x_3 + x_1}
     #[test] fn method_arg_hygiene(){
         run_renaming_test(
-            &("macro_rules! inject_x (()=>(x))
-              macro_rules! inject_self (()=>(self))
+            &("macro_rules! inject_x (()=>(x));
+              macro_rules! inject_self (()=>(self));
               struct A;
               impl A{fn get_x(&self, x: int) {self + inject_self!() + inject_x!() + x;} }",
               vec!(vec!(0),vec!(3)),
@@ -1542,8 +1543,8 @@ mod test {
         run_renaming_test(
             &("struct A;
               macro_rules! add_method (($T:ty) =>
-              (impl $T {  fn thingy(&self) {self;} }))
-              add_method!(A)",
+              (impl $T {  fn thingy(&self) {self;} }));
+              add_method!(A);",
               vec!(vec!(0)),
               true),
             0)
@@ -1553,7 +1554,7 @@ mod test {
     // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};}
     #[test] fn issue_9383(){
         run_renaming_test(
-            &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex }))
+            &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex }));
               fn q(x:int) { bad_macro!(x); }",
               vec!(vec!(1),vec!(0)),true),
             0)
@@ -1563,7 +1564,7 @@ mod test {
     // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);}
     #[test] fn closure_arg_hygiene(){
         run_renaming_test(
-            &("macro_rules! inject_x (()=>(x))
+            &("macro_rules! inject_x (()=>(x));
             fn f(){(|x : int| {(inject_x!() + x)})(3);}",
               vec!(vec!(1)),
               true),
@@ -1573,9 +1574,9 @@ mod test {
     // macro_rules in method position. Sadly, unimplemented.
     #[test] fn macro_in_method_posn(){
         expand_crate_str(
-            "macro_rules! my_method (() => (fn thirteen(&self) -> int {13}))
+            "macro_rules! my_method (() => (fn thirteen(&self) -> int {13}));
             struct A;
-            impl A{ my_method!()}
+            impl A{ my_method!(); }
             fn f(){A.thirteen;}".to_string());
     }
 
@@ -1586,7 +1587,7 @@ mod test {
             &("macro_rules! item { ($i:item) => {$i}}
               struct Entries;
               macro_rules! iterator_impl {
-              () => { item!( impl Entries { fn size_hint(&self) { self;}})}}
+              () => { item!( impl Entries { fn size_hint(&self) { self;}});}}
               iterator_impl! { }",
               vec!(vec!(0)), true),
             0)
@@ -1666,9 +1667,9 @@ mod test {
     }
 
     #[test] fn fmt_in_macro_used_inside_module_macro() {
-        let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string()))
-macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}}))
-foo_module!()
+        let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string()));
+macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}}));
+foo_module!();
 ".to_string();
         let cr = expand_crate_str(crate_str);
         // find the xx binding
diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs
index a4e06aeaf63..33936e6213f 100644
--- a/src/libsyntax/ext/mtwt.rs
+++ b/src/libsyntax/ext/mtwt.rs
@@ -108,7 +108,7 @@ pub fn apply_renames(renames: &RenameList, ctxt: SyntaxContext) -> SyntaxContext
 pub fn with_sctable<T, F>(op: F) -> T where
     F: FnOnce(&SCTable) -> T,
 {
-    thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal())
+    thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal());
     SCTABLE_KEY.with(move |slot| op(slot))
 }
 
@@ -174,7 +174,7 @@ fn with_resolve_table_mut<T, F>(op: F) -> T where
 {
     thread_local!(static RESOLVE_TABLE_KEY: RefCell<ResolveTable> = {
         RefCell::new(HashMap::new())
-    })
+    });
 
     RESOLVE_TABLE_KEY.with(move |slot| op(&mut *slot.borrow_mut()))
 }
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 45752499ad5..14e13feac98 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -100,7 +100,7 @@ pub mod rt {
         fn to_source_with_hygiene(&self) -> String;
     }
 
-    macro_rules! impl_to_source(
+    macro_rules! impl_to_source {
         (P<$t:ty>, $pp:ident) => (
             impl ToSource for P<$t> {
                 fn to_source(&self) -> String {
@@ -125,7 +125,7 @@ pub mod rt {
                 }
             }
         );
-    )
+    }
 
     fn slice_to_source<'a, T: ToSource>(sep: &'static str, xs: &'a [T]) -> String {
         xs.iter()
@@ -144,7 +144,7 @@ pub mod rt {
             .to_string()
     }
 
-    macro_rules! impl_to_source_slice(
+    macro_rules! impl_to_source_slice {
         ($t:ty, $sep:expr) => (
             impl ToSource for [$t] {
                 fn to_source(&self) -> String {
@@ -158,7 +158,7 @@ pub mod rt {
                 }
             }
         )
-    )
+    }
 
     impl ToSource for ast::Ident {
         fn to_source(&self) -> String {
@@ -172,18 +172,18 @@ pub mod rt {
         }
     }
 
-    impl_to_source!(ast::Ty, ty_to_string)
-    impl_to_source!(ast::Block, block_to_string)
-    impl_to_source!(ast::Arg, arg_to_string)
-    impl_to_source!(Generics, generics_to_string)
-    impl_to_source!(P<ast::Item>, item_to_string)
-    impl_to_source!(P<ast::Method>, method_to_string)
-    impl_to_source!(P<ast::Stmt>, stmt_to_string)
-    impl_to_source!(P<ast::Expr>, expr_to_string)
-    impl_to_source!(P<ast::Pat>, pat_to_string)
-    impl_to_source!(ast::Arm, arm_to_string)
-    impl_to_source_slice!(ast::Ty, ", ")
-    impl_to_source_slice!(P<ast::Item>, "\n\n")
+    impl_to_source! { ast::Ty, ty_to_string }
+    impl_to_source! { ast::Block, block_to_string }
+    impl_to_source! { ast::Arg, arg_to_string }
+    impl_to_source! { Generics, generics_to_string }
+    impl_to_source! { P<ast::Item>, item_to_string }
+    impl_to_source! { P<ast::Method>, method_to_string }
+    impl_to_source! { P<ast::Stmt>, stmt_to_string }
+    impl_to_source! { P<ast::Expr>, expr_to_string }
+    impl_to_source! { P<ast::Pat>, pat_to_string }
+    impl_to_source! { ast::Arm, arm_to_string }
+    impl_to_source_slice! { ast::Ty, ", " }
+    impl_to_source_slice! { P<ast::Item>, "\n\n" }
 
     impl ToSource for ast::Attribute_ {
         fn to_source(&self) -> String {
@@ -244,7 +244,7 @@ pub mod rt {
         }
     }
 
-    macro_rules! impl_to_source_int(
+    macro_rules! impl_to_source_int {
         (signed, $t:ty, $tag:ident) => (
             impl ToSource for $t {
                 fn to_source(&self) -> String {
@@ -272,23 +272,23 @@ pub mod rt {
                 }
             }
         );
-    )
+    }
 
-    impl_to_source_int!(signed, int, TyI)
-    impl_to_source_int!(signed, i8,  TyI8)
-    impl_to_source_int!(signed, i16, TyI16)
-    impl_to_source_int!(signed, i32, TyI32)
-    impl_to_source_int!(signed, i64, TyI64)
+    impl_to_source_int! { signed, int, TyI }
+    impl_to_source_int! { signed, i8,  TyI8 }
+    impl_to_source_int! { signed, i16, TyI16 }
+    impl_to_source_int! { signed, i32, TyI32 }
+    impl_to_source_int! { signed, i64, TyI64 }
 
-    impl_to_source_int!(unsigned, uint, TyU)
-    impl_to_source_int!(unsigned, u8,   TyU8)
-    impl_to_source_int!(unsigned, u16,  TyU16)
-    impl_to_source_int!(unsigned, u32,  TyU32)
-    impl_to_source_int!(unsigned, u64,  TyU64)
+    impl_to_source_int! { unsigned, uint, TyU }
+    impl_to_source_int! { unsigned, u8,   TyU8 }
+    impl_to_source_int! { unsigned, u16,  TyU16 }
+    impl_to_source_int! { unsigned, u32,  TyU32 }
+    impl_to_source_int! { unsigned, u64,  TyU64 }
 
     // Alas ... we write these out instead. All redundant.
 
-    macro_rules! impl_to_tokens(
+    macro_rules! impl_to_tokens {
         ($t:ty) => (
             impl ToTokens for $t {
                 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
@@ -296,9 +296,9 @@ pub mod rt {
                 }
             }
         )
-    )
+    }
 
-    macro_rules! impl_to_tokens_lifetime(
+    macro_rules! impl_to_tokens_lifetime {
         ($t:ty) => (
             impl<'a> ToTokens for $t {
                 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
@@ -306,36 +306,36 @@ pub mod rt {
                 }
             }
         )
-    )
-
-    impl_to_tokens!(ast::Ident)
-    impl_to_tokens!(P<ast::Item>)
-    impl_to_tokens!(P<ast::Pat>)
-    impl_to_tokens!(ast::Arm)
-    impl_to_tokens!(P<ast::Method>)
-    impl_to_tokens_lifetime!(&'a [P<ast::Item>])
-    impl_to_tokens!(ast::Ty)
-    impl_to_tokens_lifetime!(&'a [ast::Ty])
-    impl_to_tokens!(Generics)
-    impl_to_tokens!(P<ast::Stmt>)
-    impl_to_tokens!(P<ast::Expr>)
-    impl_to_tokens!(ast::Block)
-    impl_to_tokens!(ast::Arg)
-    impl_to_tokens!(ast::Attribute_)
-    impl_to_tokens_lifetime!(&'a str)
-    impl_to_tokens!(())
-    impl_to_tokens!(char)
-    impl_to_tokens!(bool)
-    impl_to_tokens!(int)
-    impl_to_tokens!(i8)
-    impl_to_tokens!(i16)
-    impl_to_tokens!(i32)
-    impl_to_tokens!(i64)
-    impl_to_tokens!(uint)
-    impl_to_tokens!(u8)
-    impl_to_tokens!(u16)
-    impl_to_tokens!(u32)
-    impl_to_tokens!(u64)
+    }
+
+    impl_to_tokens! { ast::Ident }
+    impl_to_tokens! { P<ast::Item> }
+    impl_to_tokens! { P<ast::Pat> }
+    impl_to_tokens! { ast::Arm }
+    impl_to_tokens! { P<ast::Method> }
+    impl_to_tokens_lifetime! { &'a [P<ast::Item>] }
+    impl_to_tokens! { ast::Ty }
+    impl_to_tokens_lifetime! { &'a [ast::Ty] }
+    impl_to_tokens! { Generics }
+    impl_to_tokens! { P<ast::Stmt> }
+    impl_to_tokens! { P<ast::Expr> }
+    impl_to_tokens! { ast::Block }
+    impl_to_tokens! { ast::Arg }
+    impl_to_tokens! { ast::Attribute_ }
+    impl_to_tokens_lifetime! { &'a str }
+    impl_to_tokens! { () }
+    impl_to_tokens! { char }
+    impl_to_tokens! { bool }
+    impl_to_tokens! { int }
+    impl_to_tokens! { i8 }
+    impl_to_tokens! { i16 }
+    impl_to_tokens! { i32 }
+    impl_to_tokens! { i64 }
+    impl_to_tokens! { uint }
+    impl_to_tokens! { u8 }
+    impl_to_tokens! { u16 }
+    impl_to_tokens! { u32 }
+    impl_to_tokens! { u64 }
 
     pub trait ExtParseUtils {
         fn parse_item(&self, s: String) -> P<ast::Item>;