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:
committed by
Jorge Aparicio
parent
c0b2885ee1
commit
ddb2466f6a
@@ -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 */ }) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user