Created
May 4, 2023 03:42
-
-
Save CAD97/8dd5f03729c194b19591097111a4b885 to your computer and use it in GitHub Desktop.
nounwind assertion helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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