diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/always-assert/src | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/always-assert/src')
-rw-r--r-- | vendor/always-assert/src/lib.rs | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/vendor/always-assert/src/lib.rs b/vendor/always-assert/src/lib.rs new file mode 100644 index 000000000..4cb8653b3 --- /dev/null +++ b/vendor/always-assert/src/lib.rs @@ -0,0 +1,122 @@ +//! Recoverable assertions, inspired by [the use of `assert()` in +//! SQLite](https://www.sqlite.org/assert.html). +//! +//! `never!` and `always!` return the actual value of the condition if +//! `debug_assertions` are disabled. +//! +//! Use them when terminating on assertion failure is worse than continuing. +//! +//! One example would be a critical application like a database: +//! +//! ```ignore +//! use always_assert::never; +//! +//! fn apply_transaction(&mut self, tx: Transaction) -> Result<(), TransactionAborted> { +//! let delta = self.compute_delta(&tx); +//! +//! if never!(!self.check_internal_invariant(&delta)) { +//! // Ok, something in this transaction messed up our internal state. +//! // This really shouldn't be happening, and this signifies a bug. +//! // Luckily, we can recover by just rejecting the transaction. +//! return abort_transaction(tx); +//! } +//! self.commit(delta); +//! Ok(()) +//! } +//! ``` +//! +//! Another example is assertions about non-critical functionality in usual apps +//! +//! ```ignore +//! use always_assert::never; +//! +//! let english_message = "super app installed!" +//! let mut local_message = localize(english_message); +//! if never!(local_message.is_empty(), "missing localization for {}", english_message) { +//! // We localized all the messages but this one slipper through the cracks? +//! // Better to show the english one then than to fail outright; +//! local_message = english_message; +//! } +//! println!("{}", local_message); +//! ``` + +/// Asserts that the condition is always true and returns its actual value. +/// +/// If the condition is true does nothing and and evaluates to true. +/// +/// If the condition is false: +/// * panics if `force` feature or `debug_assertions` are enabled, +/// * logs an error if `log` feature is enabled, +/// * evaluates to false. +/// +/// Accepts `format!` style arguments. +#[macro_export] +macro_rules! always { + ($cond:expr) => { + $crate::always!($cond, "assertion failed: {}", stringify!($cond)) + }; + + ($cond:expr, $fmt:literal $($arg:tt)*) => {{ + let cond = $cond; + if cfg!(debug_assertions) || $crate::__FORCE { + assert!(cond, $fmt $($arg)*); + } + if !cond { + $crate::__log_error!($fmt $($arg)*); + } + cond + }}; +} + +/// Asserts that the condition is never true and returns its actual value. +/// +/// If the condition is false does nothing and and evaluates to false. +/// +/// If the condition is true: +/// * panics if `force` feature or `debug_assertions` are enabled, +/// * logs an error if `log` feature is enabled, +/// * evaluates to true. +/// +/// Accepts `format!` style arguments. +/// +/// Empty condition is equivalent to false: +/// +/// ```ignore +/// never!("oups") ~= unreachable!("oups") +/// ``` +#[macro_export] +macro_rules! never { + (true $($tt:tt)*) => { $crate::never!((true) $($tt)*) }; + (false $($tt:tt)*) => { $crate::never!((false) $($tt)*) }; + () => { $crate::never!("assertion failed: entered unreachable code") }; + ($fmt:literal $(, $($arg:tt)*)?) => {{ + if cfg!(debug_assertions) || $crate::__FORCE { + unreachable!($fmt $(, $($arg)*)?); + } + $crate::__log_error!($fmt $(, $($arg)*)?); + }}; + + ($cond:expr) => {{ + let cond = !$crate::always!(!$cond); + cond + }}; + + ($cond:expr, $fmt:literal $($arg:tt)*) => {{ + let cond = !$crate::always!(!$cond, $fmt $($arg)*); + cond + }}; +} + +#[cfg(feature = "log")] +#[doc(hidden)] +pub use log::error as __log_error; + +#[cfg(not(feature = "log"))] +#[doc(hidden)] +#[macro_export] +macro_rules! __log_error { + ($($tt:tt)*) => {}; +} + +#[doc(hidden)] +pub const __FORCE: bool = cfg!(feature = "force"); |