auto merge of #20776 : kmcallister/rust/macro-cleanup, r=alexcrichton
r? @alexcrichton. This passes tests for me.
This commit is contained in:
commit
c133b2110b
@ -440,14 +440,18 @@ to print "I am never printed" and to run forever.
|
|||||||
|
|
||||||
# Scoping and macro import/export
|
# Scoping and macro import/export
|
||||||
|
|
||||||
Macros occupy a single global namespace. The interaction with Rust's system of
|
Macros are expanded at an early stage in compilation, before name resolution.
|
||||||
modules and crates is somewhat complex.
|
One downside is that scoping works differently for macros, compared to other
|
||||||
|
constructs in the language.
|
||||||
|
|
||||||
Definition and expansion of macros both happen in a single depth-first,
|
Definition and expansion of macros both happen in a single depth-first,
|
||||||
lexical-order traversal of a crate's source. So a macro defined at module scope
|
lexical-order traversal of a crate's source. So a macro defined at module scope
|
||||||
is visible to any subsequent code in the same module, which includes the body
|
is visible to any subsequent code in the same module, which includes the body
|
||||||
of any subsequent child `mod` items.
|
of any subsequent child `mod` items.
|
||||||
|
|
||||||
|
A macro defined within the body of a single `fn`, or anywhere else not at
|
||||||
|
module scope, is visible only within that item.
|
||||||
|
|
||||||
If a module has the `macro_use` attribute, its macros are also visible in its
|
If a module has the `macro_use` attribute, its macros are also visible in its
|
||||||
parent module after the child's `mod` item. If the parent also has `macro_use`
|
parent module after the child's `mod` item. If the parent also has `macro_use`
|
||||||
then the macros will be visible in the grandparent after the parent's `mod`
|
then the macros will be visible in the grandparent after the parent's `mod`
|
||||||
|
@ -49,15 +49,16 @@ macro_rules! panic {
|
|||||||
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[stable]
|
||||||
macro_rules! assert {
|
macro_rules! assert {
|
||||||
($cond:expr) => (
|
($cond:expr) => (
|
||||||
if !$cond {
|
if !$cond {
|
||||||
panic!(concat!("assertion failed: ", stringify!($cond)))
|
panic!(concat!("assertion failed: ", stringify!($cond)))
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
($cond:expr, $($arg:expr),+) => (
|
($cond:expr, $($arg:tt)+) => (
|
||||||
if !$cond {
|
if !$cond {
|
||||||
panic!($($arg),+)
|
panic!($($arg)+)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -75,6 +76,7 @@ macro_rules! assert {
|
|||||||
/// assert_eq!(a, b);
|
/// assert_eq!(a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[stable]
|
||||||
macro_rules! assert_eq {
|
macro_rules! assert_eq {
|
||||||
($left:expr , $right:expr) => ({
|
($left:expr , $right:expr) => ({
|
||||||
match (&($left), &($right)) {
|
match (&($left), &($right)) {
|
||||||
@ -116,6 +118,7 @@ macro_rules! assert_eq {
|
|||||||
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
|
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[stable]
|
||||||
macro_rules! debug_assert {
|
macro_rules! debug_assert {
|
||||||
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
|
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
|
||||||
}
|
}
|
||||||
@ -227,6 +230,7 @@ macro_rules! writeln {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[unstable = "relationship with panic is unclear"]
|
||||||
macro_rules! unreachable {
|
macro_rules! unreachable {
|
||||||
() => ({
|
() => ({
|
||||||
panic!("internal error: entered unreachable code")
|
panic!("internal error: entered unreachable code")
|
||||||
@ -242,6 +246,7 @@ macro_rules! unreachable {
|
|||||||
/// A standardised placeholder for marking unfinished code. It panics with the
|
/// A standardised placeholder for marking unfinished code. It panics with the
|
||||||
/// message `"not yet implemented"` when executed.
|
/// message `"not yet implemented"` when executed.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[unstable = "relationship with panic is unclear"]
|
||||||
macro_rules! unimplemented {
|
macro_rules! unimplemented {
|
||||||
() => (panic!("not yet implemented"))
|
() => (panic!("not yet implemented"))
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,8 @@
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
#[macro_reexport(write, writeln)]
|
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
|
||||||
|
unreachable, unimplemented, write, writeln)]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -60,184 +60,6 @@ macro_rules! panic {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that a boolean expression is `true` at runtime.
|
|
||||||
///
|
|
||||||
/// This will invoke the `panic!` macro if the provided expression cannot be
|
|
||||||
/// evaluated to `true` at runtime.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// // the panic message for these assertions is the stringified value of the
|
|
||||||
/// // expression given.
|
|
||||||
/// assert!(true);
|
|
||||||
/// # fn some_computation() -> bool { true }
|
|
||||||
/// assert!(some_computation());
|
|
||||||
///
|
|
||||||
/// // assert with a custom message
|
|
||||||
/// # let x = true;
|
|
||||||
/// assert!(x, "x wasn't true!");
|
|
||||||
/// # let a = 3i; let b = 27i;
|
|
||||||
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
#[stable]
|
|
||||||
macro_rules! assert {
|
|
||||||
($cond:expr) => (
|
|
||||||
if !$cond {
|
|
||||||
panic!(concat!("assertion failed: ", stringify!($cond)))
|
|
||||||
}
|
|
||||||
);
|
|
||||||
($cond:expr, $($arg:tt)+) => (
|
|
||||||
if !$cond {
|
|
||||||
panic!($($arg)+)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that two expressions are equal to each other, testing equality in
|
|
||||||
/// both directions.
|
|
||||||
///
|
|
||||||
/// On panic, this macro will print the values of the expressions.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// let a = 3i;
|
|
||||||
/// let b = 1i + 2i;
|
|
||||||
/// assert_eq!(a, b);
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
#[stable]
|
|
||||||
macro_rules! assert_eq {
|
|
||||||
($left:expr , $right:expr) => ({
|
|
||||||
match (&($left), &($right)) {
|
|
||||||
(left_val, right_val) => {
|
|
||||||
// check both directions of equality....
|
|
||||||
if !((*left_val == *right_val) &&
|
|
||||||
(*right_val == *left_val)) {
|
|
||||||
panic!("assertion failed: `(left == right) && (right == left)` \
|
|
||||||
(left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensure that a boolean expression is `true` at runtime.
|
|
||||||
///
|
|
||||||
/// This will invoke the `panic!` macro if the provided expression cannot be
|
|
||||||
/// evaluated to `true` at runtime.
|
|
||||||
///
|
|
||||||
/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
|
|
||||||
/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
|
|
||||||
/// checks that are too expensive to be present in a release build but may be
|
|
||||||
/// helpful during development.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// // the panic message for these assertions is the stringified value of the
|
|
||||||
/// // expression given.
|
|
||||||
/// debug_assert!(true);
|
|
||||||
/// # fn some_expensive_computation() -> bool { true }
|
|
||||||
/// debug_assert!(some_expensive_computation());
|
|
||||||
///
|
|
||||||
/// // assert with a custom message
|
|
||||||
/// # let x = true;
|
|
||||||
/// debug_assert!(x, "x wasn't true!");
|
|
||||||
/// # let a = 3i; let b = 27i;
|
|
||||||
/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
#[stable]
|
|
||||||
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.
|
|
||||||
///
|
|
||||||
/// On panic, this macro will print the values of the expressions.
|
|
||||||
///
|
|
||||||
/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
|
|
||||||
/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
|
|
||||||
/// useful for checks that are too expensive to be present in a release build
|
|
||||||
/// but may be helpful during development.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// let a = 3i;
|
|
||||||
/// let b = 1i + 2i;
|
|
||||||
/// debug_assert_eq!(a, b);
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! debug_assert_eq {
|
|
||||||
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A utility macro for indicating unreachable code.
|
|
||||||
///
|
|
||||||
/// This is useful any time that the compiler can't determine that some code is unreachable. For
|
|
||||||
/// example:
|
|
||||||
///
|
|
||||||
/// * Match arms with guard conditions.
|
|
||||||
/// * Loops that dynamically terminate.
|
|
||||||
/// * Iterators that dynamically terminate.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// This will always panic.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// Match arms:
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// fn foo(x: Option<int>) {
|
|
||||||
/// match x {
|
|
||||||
/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
|
|
||||||
/// Some(n) if n < 0 => println!("Some(Negative)"),
|
|
||||||
/// Some(_) => unreachable!(), // compile error if commented out
|
|
||||||
/// None => println!("None")
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Iterators:
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
|
|
||||||
/// for i in std::iter::count(0_u32, 1) {
|
|
||||||
/// if 3*i < i { panic!("u32 overflow"); }
|
|
||||||
/// if x < 3*i { return i-1; }
|
|
||||||
/// }
|
|
||||||
/// unreachable!();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[macro_export]
|
|
||||||
#[unstable = "relationship with panic is unclear"]
|
|
||||||
macro_rules! unreachable {
|
|
||||||
() => ({
|
|
||||||
panic!("internal error: entered unreachable code")
|
|
||||||
});
|
|
||||||
($msg:expr) => ({
|
|
||||||
unreachable!("{}", $msg)
|
|
||||||
});
|
|
||||||
($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]
|
|
||||||
#[unstable = "relationship with panic is unclear"]
|
|
||||||
macro_rules! unimplemented {
|
|
||||||
() => (panic!("not yet implemented"))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use the syntax described in `std::fmt` to create a value of type `String`.
|
/// Use the syntax described in `std::fmt` to create a value of type `String`.
|
||||||
/// See `std::fmt` for more information.
|
/// See `std::fmt` for more information.
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user