Add debug_assert and debug_assert_eq macros
I also switched some `assert!` calls over to `debug_assert!`. Closes #12049. RFC: 0015-assert
This commit is contained in:
parent
9f836d5a53
commit
b0b7c252d7
@ -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;
|
||||
|
||||
|
@ -93,7 +93,7 @@ impl<T> RefCell<T> {
|
||||
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
|
@ -130,6 +130,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.
|
||||
|
@ -86,8 +86,7 @@ impl<T: Send> UnsafeArc<T> {
|
||||
#[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<T: Send> UnsafeArc<T> {
|
||||
#[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<T: Send> Clone for UnsafeArc<T> {
|
||||
// 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<T> Drop for UnsafeArc<T>{
|
||||
// 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user