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]
This commit is contained in:
Patrick Walton
2014-11-14 09:18:10 -08:00
committed by Jorge Aparicio
parent c0b2885ee1
commit ddb2466f6a
222 changed files with 2330 additions and 2039 deletions

View File

@@ -37,7 +37,7 @@
/// panic!("this is a {} {message}", "fancy", message = "message");
/// ```
#[macro_export]
macro_rules! panic(
macro_rules! panic {
() => ({
panic!("explicit panic")
});
@@ -70,7 +70,7 @@ macro_rules! panic(
}
format_args!(_run_fmt, $fmt, $($arg)*)
});
)
}
/// Ensure that a boolean expression is `true` at runtime.
///
@@ -93,7 +93,7 @@ macro_rules! panic(
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
macro_rules! assert(
macro_rules! assert {
($cond:expr) => (
if !$cond {
panic!(concat!("assertion failed: ", stringify!($cond)))
@@ -104,7 +104,7 @@ macro_rules! assert(
panic!($($arg),+)
}
);
)
}
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
@@ -119,7 +119,7 @@ macro_rules! assert(
/// assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! assert_eq(
macro_rules! assert_eq {
($left:expr , $right:expr) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
@@ -132,7 +132,7 @@ macro_rules! assert_eq(
}
}
})
)
}
/// Ensure that a boolean expression is `true` at runtime.
///
@@ -160,9 +160,9 @@ macro_rules! assert_eq(
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[macro_export]
macro_rules! debug_assert(
macro_rules! debug_assert {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
)
}
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
@@ -182,9 +182,9 @@ macro_rules! debug_assert(
/// debug_assert_eq!(a, b);
/// ```
#[macro_export]
macro_rules! debug_assert_eq(
macro_rules! debug_assert_eq {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
)
}
/// A utility macro for indicating unreachable code.
///
@@ -226,7 +226,7 @@ macro_rules! debug_assert_eq(
/// }
/// ```
#[macro_export]
macro_rules! unreachable(
macro_rules! unreachable {
() => ({
panic!("internal error: entered unreachable code")
});
@@ -236,14 +236,14 @@ macro_rules! unreachable(
($fmt:expr, $($arg:tt)*) => ({
panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
});
)
}
/// A standardised placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
#[macro_export]
macro_rules! unimplemented(
macro_rules! unimplemented {
() => (panic!("not yet implemented"))
)
}
/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
@@ -257,11 +257,11 @@ macro_rules! unimplemented(
/// ```
#[macro_export]
#[stable]
macro_rules! format(
macro_rules! format {
($($arg:tt)*) => (
format_args!(::std::fmt::format, $($arg)*)
)
)
}
/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
/// See `std::fmt` for more information.
@@ -277,30 +277,30 @@ macro_rules! format(
/// ```
#[macro_export]
#[stable]
macro_rules! write(
macro_rules! write {
($dst:expr, $($arg:tt)*) => ({
let dst = &mut *$dst;
format_args!(|args| { dst.write_fmt(args) }, $($arg)*)
})
)
}
/// Equivalent to the `write!` macro, except that a newline is appended after
/// the message is written.
#[macro_export]
#[stable]
macro_rules! writeln(
macro_rules! writeln {
($dst:expr, $fmt:expr $($arg:tt)*) => (
write!($dst, concat!($fmt, "\n") $($arg)*)
)
)
}
/// Equivalent to the `println!` macro except that a newline is not printed at
/// the end of the message.
#[macro_export]
#[stable]
macro_rules! print(
macro_rules! print {
($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*))
)
}
/// Macro for printing to a task's stdout handle.
///
@@ -316,33 +316,33 @@ macro_rules! print(
/// ```
#[macro_export]
#[stable]
macro_rules! println(
macro_rules! println {
($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*))
)
}
/// Helper macro for unwrapping `Result` values while returning early with an
/// error if the value of the expression is `Err`. For more information, see
/// `std::io`.
#[macro_export]
macro_rules! try (
macro_rules! try {
($expr:expr) => ({
match $expr {
Ok(val) => val,
Err(err) => return Err(::std::error::FromError::from_error(err))
}
})
)
}
/// Create a `std::vec::Vec` containing the arguments.
#[macro_export]
macro_rules! vec[
macro_rules! vec {
($($x:expr),*) => ({
use std::slice::BoxedSliceExt;
let xs: ::std::boxed::Box<[_]> = box [$($x),*];
xs.into_vec()
});
($($x:expr,)*) => (vec![$($x),*])
]
}
/// A macro to select an event from a number of receivers.
///
@@ -394,11 +394,11 @@ macro_rules! select {
// uses. To get around this difference, we redefine the log!() macro here to be
// just a dumb version of what it should be.
#[cfg(test)]
macro_rules! log (
macro_rules! log {
($lvl:expr, $($args:tt)*) => (
if log_enabled!($lvl) { println!($($args)*) }
)
)
}
/// Built-in macros to the compiler itself.
///
@@ -430,9 +430,9 @@ pub mod builtin {
/// }, "hello {}", "world");
/// ```
#[macro_export]
macro_rules! format_args( ($closure:expr, $fmt:expr $($args:tt)*) => ({
macro_rules! format_args { ($closure:expr, $fmt:expr $($args:tt)*) => ({
/* compiler built-in */
}) )
}) }
/// Inspect an environment variable at compile time.
///
@@ -450,7 +450,7 @@ pub mod builtin {
/// println!("the $PATH variable at the time of compiling was: {}", path);
/// ```
#[macro_export]
macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) )
macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) }
/// Optionally inspect an environment variable at compile time.
///
@@ -469,7 +469,7 @@ pub mod builtin {
/// println!("the secret key might be: {}", key);
/// ```
#[macro_export]
macro_rules! option_env( ($name:expr) => ({ /* compiler built-in */ }) )
macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
/// Concatenate literals into a static byte slice.
///
@@ -489,7 +489,7 @@ pub mod builtin {
/// assert_eq!(rust[4], 255);
/// ```
#[macro_export]
macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) )
macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) }
/// Concatenate identifiers into one identifier.
///
@@ -513,7 +513,9 @@ pub mod builtin {
/// # }
/// ```
#[macro_export]
macro_rules! concat_idents( ($($e:ident),*) => ({ /* compiler built-in */ }) )
macro_rules! concat_idents {
($($e:ident),*) => ({ /* compiler built-in */ })
}
/// Concatenates literals into a static string slice.
///
@@ -531,7 +533,7 @@ pub mod builtin {
/// assert_eq!(s, "test10btrue");
/// ```
#[macro_export]
macro_rules! concat( ($($e:expr),*) => ({ /* compiler built-in */ }) )
macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) }
/// A macro which expands to the line number on which it was invoked.
///
@@ -546,7 +548,7 @@ pub mod builtin {
/// println!("defined on line: {}", current_line);
/// ```
#[macro_export]
macro_rules! line( () => ({ /* compiler built-in */ }) )
macro_rules! line { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the column number on which it was invoked.
///
@@ -561,7 +563,7 @@ pub mod builtin {
/// println!("defined on column: {}", current_col);
/// ```
#[macro_export]
macro_rules! column( () => ({ /* compiler built-in */ }) )
macro_rules! column { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the file name from which it was invoked.
///
@@ -577,7 +579,7 @@ pub mod builtin {
/// println!("defined in file: {}", this_file);
/// ```
#[macro_export]
macro_rules! file( () => ({ /* compiler built-in */ }) )
macro_rules! file { () => ({ /* compiler built-in */ }) }
/// A macro which stringifies its argument.
///
@@ -592,7 +594,7 @@ pub mod builtin {
/// assert_eq!(one_plus_one, "1 + 1");
/// ```
#[macro_export]
macro_rules! stringify( ($t:tt) => ({ /* compiler built-in */ }) )
macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) }
/// Includes a utf8-encoded file as a string.
///
@@ -606,7 +608,7 @@ pub mod builtin {
/// let secret_key = include_str!("secret-key.ascii");
/// ```
#[macro_export]
macro_rules! include_str( ($file:expr) => ({ /* compiler built-in */ }) )
macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
/// Includes a file as a byte slice.
///
@@ -620,7 +622,7 @@ pub mod builtin {
/// let secret_key = include_bin!("secret-key.bin");
/// ```
#[macro_export]
macro_rules! include_bin( ($file:expr) => ({ /* compiler built-in */ }) )
macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */ }) }
/// Expands to a string that represents the current module path.
///
@@ -640,7 +642,7 @@ pub mod builtin {
/// test::foo();
/// ```
#[macro_export]
macro_rules! module_path( () => ({ /* compiler built-in */ }) )
macro_rules! module_path { () => ({ /* compiler built-in */ }) }
/// Boolean evaluation of configuration flags.
///
@@ -661,5 +663,5 @@ pub mod builtin {
/// };
/// ```
#[macro_export]
macro_rules! cfg( ($cfg:tt) => ({ /* compiler built-in */ }) )
macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) }
}