mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Introduce more appropriate assertion mechanism
rust-analyzer is a long-running program, so we *should* handle assertion failures. See also https://www.sqlite.org/assert.html.
This commit is contained in:
parent
865e05b5b4
commit
8dc68ecdfc
8 changed files with 72 additions and 7 deletions
|
@ -1,4 +1,9 @@
|
|||
//! Convenience macros.
|
||||
|
||||
use std::{
|
||||
fmt, mem, panic,
|
||||
sync::atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
};
|
||||
#[macro_export]
|
||||
macro_rules! eprintln {
|
||||
($($tt:tt)*) => {{
|
||||
|
@ -44,3 +49,50 @@ macro_rules! impl_from {
|
|||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of `assert!` macro which allows to handle an assertion failure.
|
||||
///
|
||||
/// In release mode, it returns the condition and logs an error.
|
||||
///
|
||||
/// ```
|
||||
/// if assert_never!(impossible) {
|
||||
/// // Heh, this shouldn't have happened, but lets try to soldier on...
|
||||
/// return None;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Rust analyzer is a long-running process, and crashing really isn't an option.
|
||||
///
|
||||
/// Shamelessly stolen from: https://www.sqlite.org/assert.html
|
||||
#[macro_export]
|
||||
macro_rules! assert_never {
|
||||
($cond:expr) => { $crate::assert_always!($cond, "") };
|
||||
($cond:expr, $($fmt:tt)*) => {{
|
||||
let value = $cond;
|
||||
if value {
|
||||
$crate::on_assert_failure(
|
||||
format_args!($($fmt)*)
|
||||
);
|
||||
}
|
||||
value
|
||||
}};
|
||||
}
|
||||
|
||||
type AssertHook = fn(&panic::Location<'_>, fmt::Arguments<'_>);
|
||||
static HOOK: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
pub fn set_assert_hook(hook: AssertHook) {
|
||||
HOOK.store(hook as usize, SeqCst);
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
pub fn on_assert_failure(args: fmt::Arguments) {
|
||||
let hook: usize = HOOK.load(SeqCst);
|
||||
if hook == 0 {
|
||||
panic!("\n assertion failed: {}\n", args);
|
||||
}
|
||||
|
||||
let hook: AssertHook = unsafe { mem::transmute::<usize, AssertHook>(hook) };
|
||||
hook(panic::Location::caller(), args)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue