diff --git a/src/core/debug.rs b/src/core/debug.rs index 9e1a2e75..976781cf 100644 --- a/src/core/debug.rs +++ b/src/core/debug.rs @@ -95,7 +95,7 @@ pub fn trap() { } #[must_use] -pub fn panic_str(p: &Box) -> &'static str { +pub fn panic_str(p: &Box) -> &'static str { (**p) .downcast_ref::<&str>() .copied() diff --git a/src/core/error/mod.rs b/src/core/error/mod.rs index 7a12519b..09d98ffe 100644 --- a/src/core/error/mod.rs +++ b/src/core/error/mod.rs @@ -4,16 +4,21 @@ mod panic; mod response; mod serde; -use std::{any::Any, borrow::Cow, convert::Infallible, sync::PoisonError}; +use std::{ + any::Any, + borrow::Cow, + convert::Infallible, + sync::{OnceLock, PoisonError}, +}; pub use self::{err::visit, log::*}; #[derive(thiserror::Error)] pub enum Error { #[error("PANIC!")] - PanicAny(Box), + PanicAny(OnceLock>), #[error("PANIC! {0}")] - Panic(&'static str, Box), + Panic(&'static str, OnceLock>), // std #[error(transparent)] @@ -27,7 +32,7 @@ pub enum Error { #[error(transparent)] ParseInt(#[from] std::num::ParseIntError), #[error(transparent)] - Std(#[from] Box), + Std(#[from] Box), #[error(transparent)] SystemTime(#[from] std::time::SystemTimeError), #[error(transparent)] diff --git a/src/core/error/panic.rs b/src/core/error/panic.rs index 2e63105b..a77991cb 100644 --- a/src/core/error/panic.rs +++ b/src/core/error/panic.rs @@ -15,13 +15,16 @@ impl Error { #[must_use] #[inline] - pub fn from_panic(e: Box) -> Self { Self::Panic(debug::panic_str(&e), e) } + pub fn from_panic(e: Box) -> Self { + Self::Panic(debug::panic_str(&e), e.into()) + } #[inline] - pub fn into_panic(self) -> Box { + pub fn into_panic(self) -> Box { match self { - | Self::Panic(_, e) | Self::PanicAny(e) => e, | Self::JoinError(e) => e.into_panic(), + | Self::Panic(_, mut e) | Self::PanicAny(mut e) => + e.take().expect("Error contained panic"), | _ => Box::new(self), } } @@ -29,16 +32,18 @@ impl Error { /// Get the panic message string. #[inline] pub fn panic_str(self) -> Option<&'static str> { - self.is_panic() - .then_some(debug::panic_str(&self.into_panic())) + self.is_panic().then(|| { + let panic = self.into_panic(); + debug::panic_str(&panic) + }) } /// Check if the Error is trafficking a panic object. #[inline] pub fn is_panic(&self) -> bool { match &self { - | Self::Panic(..) | Self::PanicAny(..) => true, | Self::JoinError(e) => e.is_panic(), + | Self::Panic(..) | Self::PanicAny(..) => true, | _ => false, } }