Skip to content

Instantly share code, notes, and snippets.

@CAD97
Created May 4, 2023 03:42
Show Gist options
  • Save CAD97/8dd5f03729c194b19591097111a4b885 to your computer and use it in GitHub Desktop.
Save CAD97/8dd5f03729c194b19591097111a4b885 to your computer and use it in GitHub Desktop.
nounwind assertion helpers
#![allow(unused)]
use std::{
sync::{
atomic::{AtomicBool, Ordering::*},
Mutex,
},
thread::panicking,
};
#[macro_export]
macro_rules! should_panic {
() => {
$crate::__::should_panic($crate::__::cfg!(debug_assertions))
};
}
#[macro_export]
macro_rules! oops {
($fmt:expr $(, $($args:tt)*)?) => {
if $crate::should_panic!() {
$crate::__::panic!($fmt, $($($args)*)?);
} else {
$crate::__::log_error!($fmt, $($($args)*)?);
}
};
($msg:expr; yeet) => {
$crate::oops! { $msg; return $crate::__::Some($crate::__::None?) }
};
($msg:expr; yeet $err:expr) => {
$crate::oops! { $msg; return $crate::__::Ok($crate::__::Err($err)?) }
};
($msg:expr; $diverge:stmt) => {{
$crate::oops!($msg);
let $crate::__::true = $crate::__::false else {
#[cfg_attr(coverage_nightly, no_coverage)] $diverge
};
}};
(yeet $($err:expr)?) => { $crate::oops! { "entered unreachable code"; yeet $($err)? } };
(return $($val:expr)?) => { $crate::oops! { "entered unreachable code"; return $($val)? } };
}
#[macro_export]
macro_rules! always {
($cond:expr $(,)?) => {
// NB: slight inefficiency here; this ends up at panic_fmt, but
// an assert! with no formatting will bypass the formatting.
// the difference is marginal and not worth complexity here,
// which would be required to avoid treating code {} as fmt.
$crate::always! { $cond, "assertion failed: {}", $crate::__::stringify!($cond) }
};
($cond:expr, $($msg:tt)+) => {
$cond || { $crate::oops!($($msg)+); false }
};
($cond:expr; else yeet) => {
$crate::always! { $cond; else return $crate::__::Some($crate::__::None?) }
};
($cond:expr; else yeet $err:expr) => {
$crate::always! { $cond; else return $crate::__::Ok($crate::__::Err($err)?) }
};
($cond:expr; else $diverge:stmt) => {
let $crate::__::true = $crate::always!($cond) else {
#[cfg_attr(coverage_nightly, no_coverage)] $diverge
};
};
}
#[macro_export]
macro_rules! never {
($cond:expr $(,)?) => {
$crate::never! { $cond, "assertion failed: entered unreachable code: {}", $crate::__::stringify!($cond) }
};
($cond:expr, $($msg:tt)+) => {
$cond && { $crate::oops!($($msg)+); true }
};
($cond:expr; else yeet) => {
$crate::never! { $cond; else return $crate::__::Some($crate::__::None?) }
};
($cond:expr; else yeet $err:expr) => {
$crate::never! { $cond; else return $crate::__::Ok($crate::__::Err($err)?) }
};
($cond:expr; else $diverge:stmt) => {
let $crate::__::false = $crate::never!($cond) else {
#[cfg_attr(coverage_nightly, no_coverage)] $diverge
};
};
}
#[cfg(not(feature = "force"))]
static FORCE_ASSERTIONS: AtomicBool = AtomicBool::new(false);
pub fn force() {
#[cfg(not(feature = "force"))]
FORCE_ASSERTIONS.store(true, Relaxed);
}
#[doc(hidden)]
/// NOT PUBLIC API
pub mod __ {
use super::*;
pub use {std::{cfg, panic, stringify, format_args}, Some, None, Ok, Err, true, false};
//#[cfg(feature = "log")]
pub use log::error as __log_error;
#[cfg(any())]
#[cfg(not(feature = "log"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __log_error {
($($tt:tt)+) => {{ _ = $crate::__::format_args!($($tt)+); }};
}
pub use __log_error as log_error;
#[inline(always)]
#[cfg(feature = "force")]
pub fn should_panic(debug: bool) -> bool {
_ = debug;
true
}
#[cfg(not(feature = "force"))]
pub fn should_panic(debug: bool) -> bool {
FORCE_ASSERTIONS.load(Relaxed) || (debug && !panicking())
}
}
fn main() {
env_logger::init();
dbg!(xmain());
}
fn xmain() -> Option<()> {
always!(false; else yeet);
Some(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment