diff options
| author | Keegan McAllister <kmcallister@mozilla.com> | 2014-09-15 19:29:47 -0700 |
|---|---|---|
| committer | Keegan McAllister <kmcallister@mozilla.com> | 2015-01-05 12:00:56 -0800 |
| commit | 73806ddd0fd91066d7b903a00a080cbadcc04311 (patch) | |
| tree | 04df4f385e3e01a3f278862f190026aa6daca966 /src/libcore | |
| parent | 1c2fddc6bf6332212fe899c2cb86ae7e645f6eba (diff) | |
| download | rust-73806ddd0fd91066d7b903a00a080cbadcc04311.tar.gz rust-73806ddd0fd91066d7b903a00a080cbadcc04311.zip | |
Use $crate and macro reexport to reduce duplicated code
Many of libstd's macros are now re-exported from libcore and libcollections. Their libstd definitions have moved to a macros_stage0 module and can disappear after the next snapshot. Where the two crates had already diverged, I took the libstd versions as they're generally newer and better-tested. See e.g. d3c831b, which was a fix to libstd's assert_eq!() that didn't make it into libcore's. Fixes #16806.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/fmt/mod.rs | 5 | ||||
| -rw-r--r-- | src/libcore/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcore/macros.rs | 199 |
3 files changed, 182 insertions, 23 deletions
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 102836f8d30..b7c225c276a 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -20,12 +20,15 @@ use mem; use option::Option; use option::Option::{Some, None}; use ops::{Deref, FnOnce}; -use result::Result::{Ok, Err}; +use result::Result::Ok; use result; use slice::SliceExt; use slice; use str::{self, StrExt, Utf8Error}; +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::Err; + pub use self::num::radix; pub use self::num::Radix; pub use self::num::RadixFmt; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index d646245510d..0cda2e4a9c6 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -130,6 +130,7 @@ mod array; #[doc(hidden)] mod core { pub use panicking; + pub use fmt; } #[doc(hidden)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index e8fbd9d930f..3b21a68a292 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -30,7 +30,26 @@ macro_rules! panic { }); } -/// Runtime assertion, for details see std::macros +/// 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] macro_rules! assert { ($cond:expr) => ( @@ -38,61 +57,197 @@ macro_rules! assert { panic!(concat!("assertion failed: ", stringify!($cond))) } ); - ($cond:expr, $($arg:tt)*) => ( + ($cond:expr, $($arg:expr),+) => ( if !$cond { - panic!($($arg)*) + panic!($($arg),+) } ); } -/// Runtime assertion for equality, for details see std::macros +/// 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] macro_rules! assert_eq { - ($cond1:expr, $cond2:expr) => ({ - let c1 = $cond1; - let c2 = $cond2; - if c1 != c2 || c2 != c1 { - panic!("expressions not equal, left: {}, right: {}", c1, c2); + ($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) + } + } } }) } -/// Runtime assertion for equality, only without `--cfg ndebug` +/// 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] +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 { - ($($a:tt)*) => ({ - if cfg!(not(ndebug)) { - assert_eq!($($a)*); - } - }) + ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) } -/// Runtime assertion, disableable at compile time with `--cfg ndebug` +#[cfg(stage0)] #[macro_export] -macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) +macro_rules! try { + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) } /// Short circuiting evaluation on Err +/// +/// `libstd` contains a more general `try!` macro that uses `FromError`. +#[cfg(not(stage0))] #[macro_export] macro_rules! try { - ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) + ($e:expr) => ({ + use $crate::result::Result::{Ok, Err}; + + match $e { + Ok(e) => e, + Err(e) => return Err(e), + } + }) } -/// Writing a formatted string into a writer +/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// # #![allow(unused_must_use)] +/// +/// let mut w = Vec::new(); +/// write!(&mut w, "test"); +/// write!(&mut w, "formatted {}", "arguments"); +/// ``` #[macro_export] macro_rules! write { ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) } -/// Writing a formatted string plus a newline into a writer +/// Equivalent to the `write!` macro, except that a newline is appended after +/// the message is written. #[macro_export] +#[stable] macro_rules! writeln { ($dst:expr, $fmt:expr $($arg:tt)*) => ( write!($dst, concat!($fmt, "\n") $($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] -macro_rules! unreachable { () => (panic!("unreachable code")) } +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] +macro_rules! unimplemented { + () => (panic!("not yet implemented")) +} |
