mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-09-26 20:40:49 +00:00
Switch report handler to a global hook
This commit is contained in:
parent
96ddb39cd0
commit
608a16aa2c
@ -24,6 +24,7 @@ anyhow = "1.0.28"
|
||||
|
||||
[dependencies]
|
||||
indenter = "0.3.0"
|
||||
once_cell = "1.4.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::error::ContextError;
|
||||
use crate::{ContextCompat, EyreHandler, Report, StdError, WrapErr};
|
||||
use crate::{ContextCompat, Report, StdError, WrapErr};
|
||||
use core::fmt::{self, Debug, Display, Write};
|
||||
|
||||
#[cfg(backtrace)]
|
||||
@ -8,22 +8,18 @@ use std::backtrace::Backtrace;
|
||||
mod ext {
|
||||
use super::*;
|
||||
|
||||
pub trait StdError<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
fn ext_report<D>(self, msg: D) -> Report<H>
|
||||
pub trait StdError {
|
||||
fn ext_report<D>(self, msg: D) -> Report
|
||||
where
|
||||
D: Display + Send + Sync + 'static;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<E, H> StdError<H> for E
|
||||
impl<E> StdError for E
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
fn ext_report<D>(self, msg: D) -> Report<H>
|
||||
fn ext_report<D>(self, msg: D) -> Report
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
@ -31,11 +27,8 @@ mod ext {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H> StdError<H> for Report<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
fn ext_report<D>(self, msg: D) -> Report<H>
|
||||
impl StdError for Report {
|
||||
fn ext_report<D>(self, msg: D) -> Report
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
@ -44,19 +37,18 @@ mod ext {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E, H> WrapErr<T, E, H> for Result<T, E>
|
||||
impl<T, E> WrapErr<T, E> for Result<T, E>
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: ext::StdError<H> + Send + Sync + 'static,
|
||||
E: ext::StdError + Send + Sync + 'static,
|
||||
{
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
self.map_err(|error| error.ext_report(msg))
|
||||
}
|
||||
|
||||
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report<H>>
|
||||
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D,
|
||||
@ -64,14 +56,14 @@ where
|
||||
self.map_err(|error| error.ext_report(msg()))
|
||||
}
|
||||
|
||||
fn context<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn context<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
self.wrap_err(msg)
|
||||
}
|
||||
|
||||
fn with_context<D, F>(self, msg: F) -> Result<T, Report<H>>
|
||||
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D,
|
||||
@ -80,18 +72,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, H> ContextCompat<T, H> for Option<T>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
impl<T> ContextCompat<T> for Option<T> {
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
self.context(msg)
|
||||
}
|
||||
|
||||
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report<H>>
|
||||
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D,
|
||||
@ -99,14 +88,14 @@ where
|
||||
self.with_context(msg)
|
||||
}
|
||||
|
||||
fn context<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn context<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
self.ok_or_else(|| Report::from_display(msg))
|
||||
}
|
||||
|
||||
fn with_context<D, F>(self, msg: F) -> Result<T, Report<H>>
|
||||
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D,
|
||||
@ -152,9 +141,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<D, H> StdError for ContextError<D, Report<H>>
|
||||
impl<D> StdError for ContextError<D, Report>
|
||||
where
|
||||
H: EyreHandler,
|
||||
D: Display,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
@ -185,8 +173,8 @@ impl Write for Quoted<&mut fmt::Formatter<'_>> {
|
||||
pub(crate) mod private {
|
||||
use super::*;
|
||||
|
||||
pub trait Sealed<H: EyreHandler> {}
|
||||
pub trait Sealed {}
|
||||
|
||||
impl<T, E, H: EyreHandler> Sealed<H> for Result<T, E> where E: ext::StdError<H> {}
|
||||
impl<T, H: EyreHandler> Sealed<H> for Option<T> {}
|
||||
impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
|
||||
impl<T> Sealed for Option<T> {}
|
||||
}
|
||||
|
268
src/error.rs
268
src/error.rs
@ -10,10 +10,7 @@ use core::ptr::{self, NonNull};
|
||||
#[cfg(feature = "std")]
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
impl<H> Report<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
impl Report {
|
||||
/// Create a new error object from any error type.
|
||||
///
|
||||
/// The error type must be threadsafe and `'static`, so that the `Report`
|
||||
@ -80,17 +77,18 @@ where
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<E, H>,
|
||||
object_ref: object_ref::<E, H>,
|
||||
object_drop: object_drop::<E>,
|
||||
object_ref: object_ref::<E>,
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: object_mut::<E, H>,
|
||||
object_boxed: object_boxed::<E, H>,
|
||||
object_downcast: object_downcast::<E, H>,
|
||||
object_drop_rest: object_drop_front::<E, H>,
|
||||
object_mut: object_mut::<E>,
|
||||
object_boxed: object_boxed::<E>,
|
||||
object_downcast: object_downcast::<E>,
|
||||
object_drop_rest: object_drop_front::<E>,
|
||||
};
|
||||
|
||||
// Safety: passing vtable that operates on the right type E.
|
||||
let handler = Some(H::default(&error));
|
||||
let handler = Some(crate::capture_handler(&error));
|
||||
|
||||
unsafe { Report::construct(error, vtable, handler) }
|
||||
}
|
||||
|
||||
@ -101,18 +99,19 @@ where
|
||||
use crate::wrapper::MessageError;
|
||||
let error: MessageError<M> = MessageError(message);
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<MessageError<M>, H>,
|
||||
object_ref: object_ref::<MessageError<M>, H>,
|
||||
object_drop: object_drop::<MessageError<M>>,
|
||||
object_ref: object_ref::<MessageError<M>>,
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: object_mut::<MessageError<M>, H>,
|
||||
object_boxed: object_boxed::<MessageError<M>, H>,
|
||||
object_downcast: object_downcast::<M, H>,
|
||||
object_drop_rest: object_drop_front::<M, H>,
|
||||
object_mut: object_mut::<MessageError<M>>,
|
||||
object_boxed: object_boxed::<MessageError<M>>,
|
||||
object_downcast: object_downcast::<M>,
|
||||
object_drop_rest: object_drop_front::<M>,
|
||||
};
|
||||
|
||||
// Safety: MessageError is repr(transparent) so it is okay for the
|
||||
// vtable to allow casting the MessageError<M> to M.
|
||||
let handler = Some(H::default(&error));
|
||||
let handler = Some(crate::capture_handler(&error));
|
||||
|
||||
unsafe { Report::construct(error, vtable, handler) }
|
||||
}
|
||||
|
||||
@ -123,18 +122,19 @@ where
|
||||
use crate::wrapper::{DisplayError, NoneError};
|
||||
let error: DisplayError<M> = DisplayError(message);
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<DisplayError<M>, H>,
|
||||
object_ref: object_ref::<DisplayError<M>, H>,
|
||||
object_drop: object_drop::<DisplayError<M>>,
|
||||
object_ref: object_ref::<DisplayError<M>>,
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: object_mut::<DisplayError<M>, H>,
|
||||
object_boxed: object_boxed::<DisplayError<M>, H>,
|
||||
object_downcast: object_downcast::<M, H>,
|
||||
object_drop_rest: object_drop_front::<M, H>,
|
||||
object_mut: object_mut::<DisplayError<M>>,
|
||||
object_boxed: object_boxed::<DisplayError<M>>,
|
||||
object_downcast: object_downcast::<M>,
|
||||
object_drop_rest: object_drop_front::<M>,
|
||||
};
|
||||
|
||||
// Safety: DisplayError is repr(transparent) so it is okay for the
|
||||
// vtable to allow casting the DisplayError<M> to M.
|
||||
let handler = Some(H::default(&NoneError));
|
||||
let handler = Some(crate::capture_handler(&NoneError));
|
||||
|
||||
unsafe { Report::construct(error, vtable, handler) }
|
||||
}
|
||||
|
||||
@ -147,17 +147,18 @@ where
|
||||
let error: ContextError<D, E> = ContextError { msg, error };
|
||||
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<ContextError<D, E>, H>,
|
||||
object_ref: object_ref::<ContextError<D, E>, H>,
|
||||
object_drop: object_drop::<ContextError<D, E>>,
|
||||
object_ref: object_ref::<ContextError<D, E>>,
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: object_mut::<ContextError<D, E>, H>,
|
||||
object_boxed: object_boxed::<ContextError<D, E>, H>,
|
||||
object_downcast: context_downcast::<D, E, H>,
|
||||
object_drop_rest: context_drop_rest::<D, E, H>,
|
||||
object_mut: object_mut::<ContextError<D, E>>,
|
||||
object_boxed: object_boxed::<ContextError<D, E>>,
|
||||
object_downcast: context_downcast::<D, E>,
|
||||
object_drop_rest: context_drop_rest::<D, E>,
|
||||
};
|
||||
|
||||
// Safety: passing vtable that operates on the right type.
|
||||
let handler = Some(H::default(&error));
|
||||
let handler = Some(crate::capture_handler(&error));
|
||||
|
||||
unsafe { Report::construct(error, vtable, handler) }
|
||||
}
|
||||
|
||||
@ -165,15 +166,16 @@ where
|
||||
pub(crate) fn from_boxed(error: Box<dyn StdError + Send + Sync>) -> Self {
|
||||
use crate::wrapper::BoxedError;
|
||||
let error = BoxedError(error);
|
||||
let handler = Some(H::default(&error));
|
||||
let handler = Some(crate::capture_handler(&error));
|
||||
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<BoxedError, H>,
|
||||
object_ref: object_ref::<BoxedError, H>,
|
||||
object_drop: object_drop::<BoxedError>,
|
||||
object_ref: object_ref::<BoxedError>,
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: object_mut::<BoxedError, H>,
|
||||
object_boxed: object_boxed::<BoxedError, H>,
|
||||
object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>, H>,
|
||||
object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>, H>,
|
||||
object_mut: object_mut::<BoxedError>,
|
||||
object_boxed: object_boxed::<BoxedError>,
|
||||
object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,
|
||||
object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
|
||||
};
|
||||
|
||||
// Safety: BoxedError is repr(transparent) so it is okay for the vtable
|
||||
@ -186,7 +188,11 @@ where
|
||||
//
|
||||
// Unsafe because the given vtable must have sensible behavior on the error
|
||||
// value of type E.
|
||||
unsafe fn construct<E>(error: E, vtable: &'static ErrorVTable<H>, handler: Option<H>) -> Self
|
||||
unsafe fn construct<E>(
|
||||
error: E,
|
||||
vtable: &'static ErrorVTable,
|
||||
handler: Option<Box<dyn EyreHandler>>,
|
||||
) -> Self
|
||||
where
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
@ -201,7 +207,7 @@ where
|
||||
// result is a thin pointer. The necessary behavior for manipulating the
|
||||
// underlying ErrorImpl<E> is preserved in the vtable provided by the
|
||||
// caller rather than a builtin fat pointer vtable.
|
||||
let erased = mem::transmute::<Box<ErrorImpl<E, H>>, Box<ErrorImpl<(), H>>>(inner);
|
||||
let erased = mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner);
|
||||
let inner = ManuallyDrop::new(erased);
|
||||
Report { inner }
|
||||
}
|
||||
@ -264,16 +270,16 @@ where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
let handler = self.inner.handler.take();
|
||||
let error: ContextError<D, Report<H>> = ContextError { msg, error: self };
|
||||
let error: ContextError<D, Report> = ContextError { msg, error: self };
|
||||
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<ContextError<D, Report<H>>, H>,
|
||||
object_ref: object_ref::<ContextError<D, Report<H>>, H>,
|
||||
object_drop: object_drop::<ContextError<D, Report>>,
|
||||
object_ref: object_ref::<ContextError<D, Report>>,
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: object_mut::<ContextError<D, Report<H>>, H>,
|
||||
object_boxed: object_boxed::<ContextError<D, Report<H>>, H>,
|
||||
object_downcast: context_chain_downcast::<D, H>,
|
||||
object_drop_rest: context_chain_drop_rest::<D, H>,
|
||||
object_mut: object_mut::<ContextError<D, Report>>,
|
||||
object_boxed: object_boxed::<ContextError<D, Report>>,
|
||||
object_downcast: context_chain_downcast::<D>,
|
||||
object_drop_rest: context_chain_drop_rest::<D>,
|
||||
};
|
||||
|
||||
// Safety: passing vtable that operates on the right type.
|
||||
@ -432,32 +438,31 @@ where
|
||||
}
|
||||
|
||||
/// Get a reference to the Handler for this Report.
|
||||
pub fn handler(&self) -> &H {
|
||||
self.inner.handler.as_ref().unwrap()
|
||||
pub fn handler(&self) -> &dyn EyreHandler {
|
||||
self.inner.handler.as_ref().unwrap().as_ref()
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the Handler for this Report.
|
||||
pub fn handler_mut(&mut self) -> &mut H {
|
||||
self.inner.handler.as_mut().unwrap()
|
||||
pub fn handler_mut(&mut self) -> &mut dyn EyreHandler {
|
||||
self.inner.handler.as_mut().unwrap().as_mut()
|
||||
}
|
||||
|
||||
/// Get a reference to the Handler for this Report.
|
||||
#[doc(hidden)]
|
||||
pub fn context(&self) -> &H {
|
||||
self.inner.handler.as_ref().unwrap()
|
||||
pub fn context(&self) -> &dyn EyreHandler {
|
||||
self.inner.handler.as_ref().unwrap().as_ref()
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the Handler for this Report.
|
||||
#[doc(hidden)]
|
||||
pub fn context_mut(&mut self) -> &mut H {
|
||||
self.inner.handler.as_mut().unwrap()
|
||||
pub fn context_mut(&mut self) -> &mut dyn EyreHandler {
|
||||
self.inner.handler.as_mut().unwrap().as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<E, H> From<E> for Report<H>
|
||||
impl<E> From<E> for Report
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
fn from(error: E) -> Self {
|
||||
@ -466,7 +471,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<H: EyreHandler> Deref for Report<H> {
|
||||
impl Deref for Report {
|
||||
type Target = dyn StdError + Send + Sync + 'static;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -475,28 +480,25 @@ impl<H: EyreHandler> Deref for Report<H> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<H: EyreHandler> DerefMut for Report<H> {
|
||||
impl DerefMut for Report {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.inner.error_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: EyreHandler> Display for Report<H> {
|
||||
impl Display for Report {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.display(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: EyreHandler> Debug for Report<H> {
|
||||
impl Debug for Report {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.debug(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<H> Drop for Report<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
impl Drop for Report {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Read Box<ErrorImpl<()>> from self.
|
||||
@ -509,86 +511,72 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
struct ErrorVTable<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
object_drop: unsafe fn(Box<ErrorImpl<(), H>>),
|
||||
object_ref: unsafe fn(&ErrorImpl<(), H>) -> &(dyn StdError + Send + Sync + 'static),
|
||||
struct ErrorVTable {
|
||||
object_drop: unsafe fn(Box<ErrorImpl<()>>),
|
||||
object_ref: unsafe fn(&ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static),
|
||||
#[cfg(feature = "std")]
|
||||
object_mut: unsafe fn(&mut ErrorImpl<(), H>) -> &mut (dyn StdError + Send + Sync + 'static),
|
||||
object_mut: unsafe fn(&mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static),
|
||||
#[allow(clippy::type_complexity)]
|
||||
object_boxed: unsafe fn(Box<ErrorImpl<(), H>>) -> Box<dyn StdError + Send + Sync + 'static>,
|
||||
object_downcast: unsafe fn(&ErrorImpl<(), H>, TypeId) -> Option<NonNull<()>>,
|
||||
object_drop_rest: unsafe fn(Box<ErrorImpl<(), H>>, TypeId),
|
||||
object_boxed: unsafe fn(Box<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>,
|
||||
object_downcast: unsafe fn(&ErrorImpl<()>, TypeId) -> Option<NonNull<()>>,
|
||||
object_drop_rest: unsafe fn(Box<ErrorImpl<()>>, TypeId),
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
unsafe fn object_drop<E, H>(e: Box<ErrorImpl<(), H>>)
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
unsafe fn object_drop<E>(e: Box<ErrorImpl<()>>) {
|
||||
// Cast back to ErrorImpl<E> so that the allocator receives the correct
|
||||
// Layout to deallocate the Box's memory.
|
||||
let unerased = mem::transmute::<Box<ErrorImpl<(), H>>, Box<ErrorImpl<E, H>>>(e);
|
||||
let unerased = mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<E>>>(e);
|
||||
drop(unerased);
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
unsafe fn object_drop_front<E, H>(e: Box<ErrorImpl<(), H>>, target: TypeId)
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
unsafe fn object_drop_front<E>(e: Box<ErrorImpl<()>>, target: TypeId) {
|
||||
// Drop the fields of ErrorImpl other than E as well as the Box allocation,
|
||||
// without dropping E itself. This is used by downcast after doing a
|
||||
// ptr::read to take ownership of the E.
|
||||
let _ = target;
|
||||
let unerased = mem::transmute::<Box<ErrorImpl<(), H>>, Box<ErrorImpl<ManuallyDrop<E>, H>>>(e);
|
||||
let unerased = mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<ManuallyDrop<E>>>>(e);
|
||||
drop(unerased);
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
unsafe fn object_ref<E, H>(e: &ErrorImpl<(), H>) -> &(dyn StdError + Send + Sync + 'static)
|
||||
unsafe fn object_ref<E>(e: &ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static)
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
// Attach E's native StdError vtable onto a pointer to self._object.
|
||||
&(*(e as *const ErrorImpl<(), H> as *const ErrorImpl<E, H>))._object
|
||||
&(*(e as *const ErrorImpl<()> as *const ErrorImpl<E>))._object
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
#[cfg(feature = "std")]
|
||||
unsafe fn object_mut<E, H>(e: &mut ErrorImpl<(), H>) -> &mut (dyn StdError + Send + Sync + 'static)
|
||||
unsafe fn object_mut<E>(e: &mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static)
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
// Attach E's native StdError vtable onto a pointer to self._object.
|
||||
&mut (*(e as *mut ErrorImpl<(), H> as *mut ErrorImpl<E, H>))._object
|
||||
&mut (*(e as *mut ErrorImpl<()> as *mut ErrorImpl<E>))._object
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
unsafe fn object_boxed<E, H>(e: Box<ErrorImpl<(), H>>) -> Box<dyn StdError + Send + Sync + 'static>
|
||||
unsafe fn object_boxed<E>(e: Box<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: StdError + Send + Sync + 'static,
|
||||
H: Send + Sync + 'static,
|
||||
{
|
||||
// Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
|
||||
mem::transmute::<Box<ErrorImpl<(), H>>, Box<ErrorImpl<E, H>>>(e)
|
||||
mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<E>>>(e)
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<E>.
|
||||
unsafe fn object_downcast<E, H>(e: &ErrorImpl<(), H>, target: TypeId) -> Option<NonNull<()>>
|
||||
unsafe fn object_downcast<E>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: 'static,
|
||||
{
|
||||
if TypeId::of::<E>() == target {
|
||||
// Caller is looking for an E pointer and e is ErrorImpl<E>, take a
|
||||
// pointer to its E field.
|
||||
let unerased = e as *const ErrorImpl<(), H> as *const ErrorImpl<E, H>;
|
||||
let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<E>;
|
||||
let addr = &(*unerased)._object as *const E as *mut ();
|
||||
Some(NonNull::new_unchecked(addr))
|
||||
} else {
|
||||
@ -598,18 +586,17 @@ where
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<ContextError<D, E>>.
|
||||
#[cfg(feature = "std")]
|
||||
unsafe fn context_downcast<D, E, H>(e: &ErrorImpl<(), H>, target: TypeId) -> Option<NonNull<()>>
|
||||
unsafe fn context_downcast<D, E>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
|
||||
where
|
||||
H: EyreHandler,
|
||||
D: 'static,
|
||||
E: 'static,
|
||||
{
|
||||
if TypeId::of::<D>() == target {
|
||||
let unerased = e as *const ErrorImpl<(), H> as *const ErrorImpl<ContextError<D, E>, H>;
|
||||
let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<D, E>>;
|
||||
let addr = &(*unerased)._object.msg as *const D as *mut ();
|
||||
Some(NonNull::new_unchecked(addr))
|
||||
} else if TypeId::of::<E>() == target {
|
||||
let unerased = e as *const ErrorImpl<(), H> as *const ErrorImpl<ContextError<D, E>, H>;
|
||||
let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<D, E>>;
|
||||
let addr = &(*unerased)._object.error as *const E as *mut ();
|
||||
Some(NonNull::new_unchecked(addr))
|
||||
} else {
|
||||
@ -619,9 +606,8 @@ where
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<ContextError<D, E>>.
|
||||
#[cfg(feature = "std")]
|
||||
unsafe fn context_drop_rest<D, E, H>(e: Box<ErrorImpl<(), H>>, target: TypeId)
|
||||
unsafe fn context_drop_rest<D, E>(e: Box<ErrorImpl<()>>, target: TypeId)
|
||||
where
|
||||
H: EyreHandler,
|
||||
D: 'static,
|
||||
E: 'static,
|
||||
{
|
||||
@ -629,58 +615,54 @@ where
|
||||
// ptr::read to take ownership of that value.
|
||||
if TypeId::of::<D>() == target {
|
||||
let unerased = mem::transmute::<
|
||||
Box<ErrorImpl<(), H>>,
|
||||
Box<ErrorImpl<ContextError<ManuallyDrop<D>, E>, H>>,
|
||||
Box<ErrorImpl<()>>,
|
||||
Box<ErrorImpl<ContextError<ManuallyDrop<D>, E>>>,
|
||||
>(e);
|
||||
drop(unerased);
|
||||
} else {
|
||||
let unerased = mem::transmute::<
|
||||
Box<ErrorImpl<(), H>>,
|
||||
Box<ErrorImpl<ContextError<D, ManuallyDrop<E>>, H>>,
|
||||
Box<ErrorImpl<()>>,
|
||||
Box<ErrorImpl<ContextError<D, ManuallyDrop<E>>>>,
|
||||
>(e);
|
||||
drop(unerased);
|
||||
}
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
|
||||
unsafe fn context_chain_downcast<D, H>(e: &ErrorImpl<(), H>, target: TypeId) -> Option<NonNull<()>>
|
||||
unsafe fn context_chain_downcast<D>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
|
||||
where
|
||||
H: EyreHandler,
|
||||
D: 'static,
|
||||
{
|
||||
if TypeId::of::<D>() == target {
|
||||
let unerased =
|
||||
e as *const ErrorImpl<(), H> as *const ErrorImpl<ContextError<D, Report<H>>, H>;
|
||||
let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<D, Report>>;
|
||||
let addr = &(*unerased)._object.msg as *const D as *mut ();
|
||||
Some(NonNull::new_unchecked(addr))
|
||||
} else {
|
||||
// Recurse down the context chain per the inner error's vtable.
|
||||
let unerased =
|
||||
e as *const ErrorImpl<(), H> as *const ErrorImpl<ContextError<D, Report<H>>, H>;
|
||||
let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<D, Report>>;
|
||||
let source = &(*unerased)._object.error;
|
||||
(source.inner.vtable.object_downcast)(&source.inner, target)
|
||||
}
|
||||
}
|
||||
|
||||
// Safety: requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
|
||||
unsafe fn context_chain_drop_rest<D, H>(e: Box<ErrorImpl<(), H>>, target: TypeId)
|
||||
unsafe fn context_chain_drop_rest<D>(e: Box<ErrorImpl<()>>, target: TypeId)
|
||||
where
|
||||
H: EyreHandler,
|
||||
D: 'static,
|
||||
{
|
||||
// Called after downcasting by value to either the D or one of the causes
|
||||
// and doing a ptr::read to take ownership of that value.
|
||||
if TypeId::of::<D>() == target {
|
||||
let unerased = mem::transmute::<
|
||||
Box<ErrorImpl<(), H>>,
|
||||
Box<ErrorImpl<ContextError<ManuallyDrop<D>, Report<H>>, H>>,
|
||||
Box<ErrorImpl<()>>,
|
||||
Box<ErrorImpl<ContextError<ManuallyDrop<D>, Report>>>,
|
||||
>(e);
|
||||
// Drop the entire rest of the data structure rooted in the next Report.
|
||||
drop(unerased);
|
||||
} else {
|
||||
let unerased = mem::transmute::<
|
||||
Box<ErrorImpl<(), H>>,
|
||||
Box<ErrorImpl<ContextError<D, ManuallyDrop<Report<H>>>, H>>,
|
||||
Box<ErrorImpl<()>>,
|
||||
Box<ErrorImpl<ContextError<D, ManuallyDrop<Report>>>>,
|
||||
>(e);
|
||||
// Read out a ManuallyDrop<Box<ErrorImpl<()>>> from the next error.
|
||||
let inner = ptr::read(&unerased._object.error.inner);
|
||||
@ -693,12 +675,9 @@ where
|
||||
|
||||
// repr C to ensure that E remains in the final position.
|
||||
#[repr(C)]
|
||||
pub(crate) struct ErrorImpl<E, H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
vtable: &'static ErrorVTable<H>,
|
||||
pub(crate) handler: Option<H>,
|
||||
pub(crate) struct ErrorImpl<E> {
|
||||
vtable: &'static ErrorVTable,
|
||||
pub(crate) handler: Option<Box<dyn EyreHandler>>,
|
||||
// NOTE: Don't use directly. Use only through vtable. Erased type may have
|
||||
// different alignment.
|
||||
_object: E,
|
||||
@ -712,22 +691,16 @@ pub(crate) struct ContextError<D, E> {
|
||||
pub(crate) error: E,
|
||||
}
|
||||
|
||||
impl<E, H> ErrorImpl<E, H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
fn erase(&self) -> &ErrorImpl<(), H> {
|
||||
impl<E> ErrorImpl<E> {
|
||||
fn erase(&self) -> &ErrorImpl<()> {
|
||||
// Erase the concrete type of E but preserve the vtable in self.vtable
|
||||
// for manipulating the resulting thin pointer. This is analogous to an
|
||||
// unsize coersion.
|
||||
unsafe { &*(self as *const ErrorImpl<E, H> as *const ErrorImpl<(), H>) }
|
||||
unsafe { &*(self as *const ErrorImpl<E> as *const ErrorImpl<()>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<H> ErrorImpl<(), H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
impl ErrorImpl<()> {
|
||||
pub(crate) fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
|
||||
// Use vtable to attach E's native StdError vtable for the right
|
||||
// original type E.
|
||||
@ -746,9 +719,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, H> StdError for ErrorImpl<E, H>
|
||||
impl<E> StdError for ErrorImpl<E>
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: StdError,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
@ -756,9 +728,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, H> Debug for ErrorImpl<E, H>
|
||||
impl<E> Debug for ErrorImpl<E>
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: Debug,
|
||||
{
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -766,9 +737,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, H> Display for ErrorImpl<E, H>
|
||||
impl<E> Display for ErrorImpl<E>
|
||||
where
|
||||
H: EyreHandler,
|
||||
E: Display,
|
||||
{
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -776,8 +746,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: EyreHandler> From<Report<H>> for Box<dyn StdError + Send + Sync + 'static> {
|
||||
fn from(error: Report<H>) -> Self {
|
||||
impl From<Report> for Box<dyn StdError + Send + Sync + 'static> {
|
||||
fn from(error: Report) -> Self {
|
||||
let outer = ManuallyDrop::new(error);
|
||||
unsafe {
|
||||
// Read Box<ErrorImpl<()>> from error. Can't move it out because
|
||||
@ -792,21 +762,21 @@ impl<H: EyreHandler> From<Report<H>> for Box<dyn StdError + Send + Sync + 'stati
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: EyreHandler> From<Report<H>> for Box<dyn StdError + 'static> {
|
||||
fn from(error: Report<H>) -> Self {
|
||||
impl From<Report> for Box<dyn StdError + 'static> {
|
||||
fn from(error: Report) -> Self {
|
||||
Box::<dyn StdError + Send + Sync>::from(error)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<H: EyreHandler> AsRef<dyn StdError + Send + Sync> for Report<H> {
|
||||
impl AsRef<dyn StdError + Send + Sync> for Report {
|
||||
fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<H: EyreHandler> AsRef<dyn StdError> for Report<H> {
|
||||
impl AsRef<dyn StdError> for Report {
|
||||
fn as_ref(&self) -> &(dyn StdError + 'static) {
|
||||
&**self
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
use crate::error::ErrorImpl;
|
||||
use crate::EyreHandler;
|
||||
use core::fmt;
|
||||
|
||||
impl<H> ErrorImpl<(), H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
impl ErrorImpl<()> {
|
||||
pub(crate) fn display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.handler
|
||||
.as_ref()
|
||||
|
36
src/kind.rs
36
src/kind.rs
@ -45,7 +45,7 @@
|
||||
// let error = $msg;
|
||||
// (&error).eyre_kind().new(error)
|
||||
|
||||
use crate::{EyreHandler, Report};
|
||||
use crate::Report;
|
||||
use core::fmt::{Debug, Display};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@ -63,7 +63,7 @@ pub trait AdhocKind: Sized {
|
||||
impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {}
|
||||
|
||||
impl Adhoc {
|
||||
pub fn new<M, H: EyreHandler>(self, message: M) -> Report<H>
|
||||
pub fn new<M>(self, message: M) -> Report
|
||||
where
|
||||
M: Display + Debug + Send + Sync + 'static,
|
||||
{
|
||||
@ -71,27 +71,21 @@ impl Adhoc {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Trait<H>(std::marker::PhantomData<H>);
|
||||
pub struct Trait;
|
||||
|
||||
pub trait TraitKind<H>: Sized {
|
||||
pub trait TraitKind: Sized {
|
||||
#[inline]
|
||||
fn eyre_kind(&self) -> Trait<H> {
|
||||
Trait(std::marker::PhantomData)
|
||||
fn eyre_kind(&self) -> Trait {
|
||||
Trait
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, H> TraitKind<H> for E
|
||||
where
|
||||
E: Into<Report<H>>,
|
||||
H: EyreHandler,
|
||||
{
|
||||
}
|
||||
impl<E> TraitKind for E where E: Into<Report> {}
|
||||
|
||||
impl<H> Trait<H> {
|
||||
pub fn new<E>(self, error: E) -> Report<H>
|
||||
impl Trait {
|
||||
pub fn new<E>(self, error: E) -> Report
|
||||
where
|
||||
E: Into<Report<H>>,
|
||||
H: EyreHandler,
|
||||
E: Into<Report>,
|
||||
{
|
||||
error.into()
|
||||
}
|
||||
@ -113,7 +107,7 @@ impl BoxedKind for Box<dyn StdError + Send + Sync> {}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Boxed {
|
||||
pub fn new<H: EyreHandler>(self, error: Box<dyn StdError + Send + Sync>) -> Report<H> {
|
||||
pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Report {
|
||||
Report::from_boxed(error)
|
||||
}
|
||||
}
|
||||
@ -122,16 +116,12 @@ impl Boxed {
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::eyre;
|
||||
use crate::EyreHandler;
|
||||
use std::num::ParseIntError;
|
||||
|
||||
struct NonDefaultHandler;
|
||||
|
||||
impl EyreHandler for NonDefaultHandler {
|
||||
#[allow(unused_variables)]
|
||||
fn default(error: &(dyn StdError + 'static)) -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
_error: &(dyn StdError + 'static),
|
||||
@ -145,7 +135,7 @@ mod test {
|
||||
s.parse::<i32>()
|
||||
}
|
||||
|
||||
fn _throw_error() -> Result<(), Report<NonDefaultHandler>> {
|
||||
fn _throw_error() -> Result<(), Report> {
|
||||
match _parse("abc") {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(eyre!(e).wrap_err("try parsing an actual number")),
|
||||
|
166
src/lib.rs
166
src/lib.rs
@ -399,6 +399,7 @@ pub trait StdError: Debug + Display {
|
||||
pub use eyre as format_err;
|
||||
/// Compatibility re-export of `eyre` for interopt with `anyhow`
|
||||
pub use eyre as anyhow;
|
||||
use once_cell::sync::OnceCell;
|
||||
#[doc(hidden)]
|
||||
pub use DefaultHandler as DefaultContext;
|
||||
#[doc(hidden)]
|
||||
@ -499,11 +500,55 @@ pub use WrapErr as Context;
|
||||
/// # Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Report<H = DefaultHandler>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
inner: ManuallyDrop<Box<ErrorImpl<(), H>>>,
|
||||
pub struct Report {
|
||||
inner: ManuallyDrop<Box<ErrorImpl<()>>>,
|
||||
}
|
||||
|
||||
type ErrorHook =
|
||||
Box<dyn Fn(&(dyn StdError + 'static)) -> Box<dyn EyreHandler> + Sync + Send + 'static>;
|
||||
|
||||
static HOOK: OnceCell<ErrorHook> = OnceCell::new();
|
||||
|
||||
///
|
||||
pub fn set_hook(hook: ErrorHook) -> Result<(), Box<dyn StdError + Send + Sync + 'static>> {
|
||||
HOOK.set(hook)
|
||||
.map_err(|_| "unable to set global hook".into())
|
||||
}
|
||||
|
||||
fn capture_handler(error: &(dyn StdError + 'static)) -> Box<dyn EyreHandler> {
|
||||
HOOK.get_or_init(|| Box::new(DefaultHandler::default_with))(error)
|
||||
}
|
||||
|
||||
impl dyn EyreHandler {
|
||||
///
|
||||
pub fn is<T: EyreHandler>(&self) -> bool {
|
||||
// Get `TypeId` of the type this function is instantiated with.
|
||||
let t = core::any::TypeId::of::<T>();
|
||||
|
||||
// Get `TypeId` of the type in the trait object (`self`).
|
||||
let concrete = self.type_id();
|
||||
|
||||
// Compare both `TypeId`s on equality.
|
||||
t == concrete
|
||||
}
|
||||
|
||||
///
|
||||
pub fn downcast_ref<T: EyreHandler>(&self) -> Option<&T> {
|
||||
if self.is::<T>() {
|
||||
unsafe { Some(&*(self as *const dyn EyreHandler as *const T)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn downcast_mut<T: EyreHandler>(&mut self) -> Option<&mut T> {
|
||||
if self.is::<T>() {
|
||||
unsafe { Some(&mut *(self as *mut dyn EyreHandler as *mut T)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error Report Handler trait for customizing `eyre::Report`
|
||||
@ -565,64 +610,7 @@ where
|
||||
/// type Report = eyre::Report<Handler>;
|
||||
/// type Result<T, E = eyre::Report<Handler>> = core::result::Result<T, E>;
|
||||
/// ```
|
||||
pub trait EyreHandler: Sized + Send + Sync + 'static {
|
||||
/// Default construct a `Handler` when constructing a `Report`.
|
||||
///
|
||||
/// This method provides a reference to the error being wrapped to support conditional
|
||||
/// capturing of context like `backtrace` depending on whether the source error already
|
||||
/// captured one.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use backtrace::Backtrace;
|
||||
/// use eyre::EyreHandler;
|
||||
/// # use eyre::Chain;
|
||||
/// use std::error::Error;
|
||||
///
|
||||
/// pub struct Handler {
|
||||
/// backtrace: Backtrace,
|
||||
/// }
|
||||
///
|
||||
/// impl EyreHandler for Handler {
|
||||
/// # #[allow(unused_variables)]
|
||||
/// fn default(error: &(dyn Error + 'static)) -> Self {
|
||||
/// let backtrace = Backtrace::new();
|
||||
///
|
||||
/// Self { backtrace }
|
||||
/// }
|
||||
///
|
||||
/// // ...
|
||||
/// # fn debug(
|
||||
/// # &self,
|
||||
/// # error: &(dyn Error + 'static),
|
||||
/// # f: &mut core::fmt::Formatter<'_>,
|
||||
/// # ) -> core::fmt::Result {
|
||||
/// # use core::fmt::Write as _;
|
||||
/// # if f.alternate() {
|
||||
/// # return core::fmt::Debug::fmt(error, f);
|
||||
/// # }
|
||||
/// # write!(f, "{}", error)?;
|
||||
/// # if let Some(cause) = error.source() {
|
||||
/// # write!(f, "\n\nCaused by:")?;
|
||||
/// # let multiple = cause.source().is_some();
|
||||
/// # for (n, error) in Chain::new(cause).enumerate() {
|
||||
/// # writeln!(f)?;
|
||||
/// # if multiple {
|
||||
/// # write!(indenter::indented(f).ind(n), "{}", error)?;
|
||||
/// # } else {
|
||||
/// # write!(indenter::indented(f), "{}", error)?;
|
||||
/// # }
|
||||
/// # }
|
||||
/// # }
|
||||
/// # let backtrace = &self.backtrace;
|
||||
/// # write!(f, "\n\nStack backtrace:\n{:?}", backtrace)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// }
|
||||
/// ```
|
||||
fn default(err: &(dyn StdError + 'static)) -> Self;
|
||||
|
||||
pub trait EyreHandler: core::any::Any + Send + Sync {
|
||||
/// Define the report format
|
||||
///
|
||||
/// Used to override the report format of `eyre::Report`
|
||||
@ -715,6 +703,15 @@ pub struct DefaultHandler {
|
||||
backtrace: Option<Backtrace>,
|
||||
}
|
||||
|
||||
impl DefaultHandler {
|
||||
#[allow(unused_variables)]
|
||||
fn default_with(error: &(dyn StdError + 'static)) -> Box<dyn EyreHandler> {
|
||||
let backtrace = backtrace_if_absent!(error);
|
||||
|
||||
Box::new(Self { backtrace })
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for DefaultHandler {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("DefaultHandler")
|
||||
@ -730,13 +727,6 @@ impl core::fmt::Debug for DefaultHandler {
|
||||
}
|
||||
|
||||
impl EyreHandler for DefaultHandler {
|
||||
#[allow(unused_variables)]
|
||||
fn default(error: &(dyn StdError + 'static)) -> Self {
|
||||
let backtrace = backtrace_if_absent!(error);
|
||||
|
||||
Self { backtrace }
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
error: &(dyn StdError + 'static),
|
||||
@ -855,7 +845,7 @@ pub struct Chain<'a> {
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub type Result<T, E = Report<DefaultHandler>> = core::result::Result<T, E>;
|
||||
pub type Result<T, E = Report> = core::result::Result<T, E>;
|
||||
|
||||
/// Provides the `wrap_err` method for `Result`.
|
||||
///
|
||||
@ -1022,29 +1012,26 @@ pub type Result<T, E = Report<DefaultHandler>> = core::result::Result<T, E>;
|
||||
/// # panic!("expected downcast to succeed");
|
||||
/// }
|
||||
/// ```
|
||||
pub trait WrapErr<T, E, H>: context::private::Sealed<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
pub trait WrapErr<T, E>: context::private::Sealed {
|
||||
/// Wrap the error value with a new adhoc error
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static;
|
||||
|
||||
/// Wrap the error value with a new adhoc error that is evaluated lazily
|
||||
/// only once an error does occur.
|
||||
fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report<H>>
|
||||
fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D;
|
||||
|
||||
/// Compatibility re-export of wrap_err for interopt with `anyhow`
|
||||
fn context<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn context<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static;
|
||||
|
||||
/// Compatibility re-export of wrap_err_with for interopt with `anyhow`
|
||||
fn with_context<D, F>(self, f: F) -> Result<T, Report<H>>
|
||||
fn with_context<D, F>(self, f: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D;
|
||||
@ -1093,30 +1080,27 @@ where
|
||||
/// .ok_or_else(|| eyre!("the thing wasnt in the list"))
|
||||
/// }
|
||||
/// ```
|
||||
pub trait ContextCompat<T, H>: context::private::Sealed<H>
|
||||
where
|
||||
H: EyreHandler,
|
||||
{
|
||||
pub trait ContextCompat<T>: context::private::Sealed {
|
||||
/// Compatibility version of `wrap_err` for creating new errors with new source on `Option`
|
||||
/// when porting from `anyhow`
|
||||
fn context<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn context<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static;
|
||||
|
||||
/// Compatibility version of `wrap_err_with` for creating new errors with new source on `Option`
|
||||
/// when porting from `anyhow`
|
||||
fn with_context<D, F>(self, f: F) -> Result<T, Report<H>>
|
||||
fn with_context<D, F>(self, f: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D;
|
||||
|
||||
/// Compatibility re-export of `context` for porting from `anyhow` to `eyre`
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report<H>>
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static;
|
||||
|
||||
/// Compatibility re-export of `with_context` for porting from `anyhow` to `eyre`
|
||||
fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report<H>>
|
||||
fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> D;
|
||||
@ -1125,12 +1109,9 @@ where
|
||||
// Not public API. Referenced by macro-generated code.
|
||||
#[doc(hidden)]
|
||||
pub mod private {
|
||||
use crate::{EyreHandler, Report};
|
||||
use crate::Report;
|
||||
use core::fmt::{Debug, Display};
|
||||
|
||||
// #[cfg(backtrace)]
|
||||
// use std::backtrace::Backtrace;
|
||||
|
||||
pub use core::result::Result::Err;
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -1141,9 +1122,8 @@ pub mod private {
|
||||
pub use crate::kind::BoxedKind;
|
||||
}
|
||||
|
||||
pub fn new_adhoc<M, H>(message: M) -> Report<H>
|
||||
pub fn new_adhoc<M>(message: M) -> Report
|
||||
where
|
||||
H: EyreHandler,
|
||||
M: Display + Debug + Send + Sync + 'static,
|
||||
{
|
||||
Report::from_adhoc(message)
|
||||
|
@ -3,7 +3,7 @@ mod drop;
|
||||
|
||||
use self::common::*;
|
||||
use self::drop::{DetectDrop, Flag};
|
||||
use eyre::{DefaultContext, Report};
|
||||
use eyre::Report;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::{self, Display};
|
||||
use std::io;
|
||||
@ -90,7 +90,7 @@ fn test_large_alignment() {
|
||||
|
||||
impl StdError for LargeAlignedError {}
|
||||
|
||||
let error: Report<DefaultContext> = Report::new(LargeAlignedError("oh no!"));
|
||||
let error = Report::new(LargeAlignedError("oh no!"));
|
||||
assert_eq!(
|
||||
"oh no!",
|
||||
error.downcast_ref::<LargeAlignedError>().unwrap().0
|
||||
|
@ -1,7 +1,6 @@
|
||||
mod drop;
|
||||
|
||||
use self::drop::{DetectDrop, Flag};
|
||||
use eyre::DefaultContext;
|
||||
use eyre::Report;
|
||||
use std::marker::Unpin;
|
||||
use std::mem;
|
||||
@ -28,6 +27,6 @@ fn test_autotraits() {
|
||||
#[test]
|
||||
fn test_drop() {
|
||||
let has_dropped = Flag::new();
|
||||
drop(Report::<DefaultContext>::new(DetectDrop::new(&has_dropped)));
|
||||
drop(Report::new(DetectDrop::new(&has_dropped)));
|
||||
assert!(has_dropped.get());
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ fn test_literal_source() {
|
||||
#[test]
|
||||
fn test_variable_source() {
|
||||
let msg = "oh no!";
|
||||
let error: Report = eyre!(msg);
|
||||
let error = eyre!(msg);
|
||||
assert!(error.source().is_none());
|
||||
|
||||
let msg = msg.to_owned();
|
||||
|
Loading…
x
Reference in New Issue
Block a user