diff --git a/src/libcollections/hashmap.rs b/src/libcollections/hashmap.rs index 302cc611f381e..ce8e1474ee50b 100644 --- a/src/libcollections/hashmap.rs +++ b/src/libcollections/hashmap.rs @@ -278,8 +278,7 @@ mod table { /// the appropriate types to pass on to most of the other functions in /// this module. pub fn peek(&self, index: uint) -> BucketState { - // FIXME #12049 - if cfg!(test) { assert!(index < self.capacity) } + debug_assert!(index < self.capacity); let idx = index as int; let hash = unsafe { *self.hashes.offset(idx) }; @@ -306,8 +305,7 @@ mod table { let idx = index.idx; unsafe { - // FIXME #12049 - if cfg!(test) { assert!(*self.hashes.offset(idx) != EMPTY_BUCKET) } + debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET); (&'a *self.keys.offset(idx), &'a *self.vals.offset(idx)) } @@ -319,8 +317,7 @@ mod table { let idx = index.idx; unsafe { - // FIXME #12049 - if cfg!(test) { assert!(*self.hashes.offset(idx) != EMPTY_BUCKET) } + debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET); (&'a *self.keys.offset(idx), &'a mut *self.vals.offset(idx)) } @@ -332,8 +329,7 @@ mod table { let idx = index.idx; unsafe { - // FIXME #12049 - if cfg!(test) { assert!(*self.hashes.offset(idx) != EMPTY_BUCKET) } + debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET); (transmute(self.hashes.offset(idx)), &'a mut *self.keys.offset(idx), &'a mut *self.vals.offset(idx)) @@ -351,8 +347,7 @@ mod table { let idx = index.idx; unsafe { - // FIXME #12049 - if cfg!(test) { assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET) } + debug_assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET); *self.hashes.offset(idx) = hash.inspect(); move_val_init(&mut *self.keys.offset(idx), k); move_val_init(&mut *self.vals.offset(idx), v); @@ -371,8 +366,7 @@ mod table { let idx = index.idx; unsafe { - // FIXME #12049 - if cfg!(test) { assert!(*self.hashes.offset(idx) != EMPTY_BUCKET) } + debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET); *self.hashes.offset(idx) = EMPTY_BUCKET; diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index ec064f4f5ec73..1e4faf1a899e6 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -93,7 +93,7 @@ impl RefCell { /// Consumes the `RefCell`, returning the wrapped value. pub fn unwrap(self) -> T { - assert!(self.borrow.get() == UNUSED); + debug_assert!(self.borrow.get() == UNUSED); unsafe{self.value.unwrap()} } @@ -181,7 +181,7 @@ pub struct Ref<'b, T> { impl<'b, T> Drop for Ref<'b, T> { fn drop(&mut self) { let borrow = self.parent.borrow.get(); - assert!(borrow != WRITING && borrow != UNUSED); + debug_assert!(borrow != WRITING && borrow != UNUSED); self.parent.borrow.set(borrow - 1); } } @@ -202,7 +202,7 @@ pub struct RefMut<'b, T> { impl<'b, T> Drop for RefMut<'b, T> { fn drop(&mut self) { let borrow = self.parent.borrow.get(); - assert!(borrow == WRITING); + debug_assert!(borrow == WRITING); self.parent.borrow.set(UNUSED); } } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index dbaef3358043e..b04ca63e55e4d 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -90,11 +90,6 @@ macro_rules! assert( fail!("assertion failed: {:s}", stringify!($cond)) } ); - ($cond:expr, $msg:expr) => ( - if !$cond { - fail!($msg) - } - ); ($cond:expr, $($arg:expr),+) => ( if !$cond { fail!($($arg),+) @@ -130,6 +125,58 @@ macro_rules! assert_eq( }) ) +/// Ensure that a boolean expression is `true` at runtime. +/// +/// This will invoke the `fail!` 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 failure 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 = 3; let b = 27; +/// 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 failure, 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 = 3; +/// let b = 1 + 2; +/// 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. It will fail if /// executed. This is occasionally useful to put after loops that never /// terminate normally, but instead directly return from a function. diff --git a/src/libstd/sync/arc.rs b/src/libstd/sync/arc.rs index 7ac7700d8d348..8d6d1c222cf55 100644 --- a/src/libstd/sync/arc.rs +++ b/src/libstd/sync/arc.rs @@ -86,8 +86,7 @@ impl UnsafeArc { #[inline] pub fn get(&self) -> *mut T { unsafe { - // FIXME(#12049): this needs some sort of debug assertion - if cfg!(test) { assert!((*self.data).count.load(Relaxed) > 0); } + debug_assert!((*self.data).count.load(Relaxed) > 0); return (*self.data).data.get(); } } @@ -97,8 +96,7 @@ impl UnsafeArc { #[inline] pub fn get_immut(&self) -> *T { unsafe { - // FIXME(#12049): this needs some sort of debug assertion - if cfg!(test) { assert!((*self.data).count.load(Relaxed) > 0); } + debug_assert!((*self.data).count.load(Relaxed) > 0); return (*self.data).data.get() as *T; } } @@ -125,8 +123,7 @@ impl Clone for UnsafeArc { // synchronization. // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) let old_count = (*self.data).count.fetch_add(1, Relaxed); - // FIXME(#12049): this needs some sort of debug assertion - if cfg!(test) { assert!(old_count >= 1); } + debug_assert!(old_count >= 1); return UnsafeArc { data: self.data }; } } @@ -144,8 +141,7 @@ impl Drop for UnsafeArc{ // Because `fetch_sub` is already atomic, we do not need to synchronize with other // threads unless we are going to delete the object. let old_count = (*self.data).count.fetch_sub(1, Release); - // FIXME(#12049): this needs some sort of debug assertion - if cfg!(test) { assert!(old_count >= 1); } + debug_assert!(old_count >= 1); if old_count == 1 { // This fence is needed to prevent reordering of use of the data and deletion of // the data. Because it is marked `Release`, the decreasing of the reference count