about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorKeegan McAllister <kmcallister@mozilla.com>2014-09-15 19:29:47 -0700
committerKeegan McAllister <kmcallister@mozilla.com>2015-01-05 12:00:56 -0800
commit73806ddd0fd91066d7b903a00a080cbadcc04311 (patch)
tree04df4f385e3e01a3f278862f190026aa6daca966 /src/libcore
parent1c2fddc6bf6332212fe899c2cb86ae7e645f6eba (diff)
downloadrust-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.rs5
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/macros.rs199
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"))
+}