mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-09-27 21:14:34 +00:00
Support context on Option
This commit is contained in:
parent
c06155e5fb
commit
aa2d08087c
@ -9,5 +9,5 @@ script: cargo test
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- rust: 1.32.0
|
||||
- rust: 1.34.0
|
||||
script: cargo check
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::Error;
|
||||
use std::convert::Infallible;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
|
||||
@ -103,6 +104,43 @@ impl<T> Context<T, Error> for Result<T, Error> {
|
||||
}
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// # type T = ();
|
||||
/// #
|
||||
/// use anyhow::{Context, Result};
|
||||
///
|
||||
/// fn maybe_get() -> Option<T> {
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// ...
|
||||
/// # };
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// fn demo() -> Result<()> {
|
||||
/// let t = maybe_get().context("there is no T")?;
|
||||
/// # const IGNORE: &str = stringify! {
|
||||
/// ...
|
||||
/// # };
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
/// ```
|
||||
impl<T> Context<T, Infallible> for Option<T> {
|
||||
fn context<C>(self, context: C) -> Result<T, Error>
|
||||
where
|
||||
C: Display + Send + Sync + 'static,
|
||||
{
|
||||
self.ok_or_else(|| Error::from_display(context, backtrace!()))
|
||||
}
|
||||
|
||||
fn with_context<C, F>(self, context: F) -> Result<T, Error>
|
||||
where
|
||||
C: Display + Send + Sync + 'static,
|
||||
F: FnOnce() -> C,
|
||||
{
|
||||
self.ok_or_else(|| Error::from_display(context(), backtrace!()))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ContextError<E, C> {
|
||||
pub error: E,
|
||||
pub context: C,
|
||||
|
35
src/error.rs
35
src/error.rs
@ -59,6 +59,18 @@ impl Error {
|
||||
unsafe { Error::construct(error, type_id, backtrace) }
|
||||
}
|
||||
|
||||
pub(crate) fn from_display<M>(message: M, backtrace: Option<Backtrace>) -> Self
|
||||
where
|
||||
M: Display + Send + Sync + 'static,
|
||||
{
|
||||
let error = DisplayError(message);
|
||||
let type_id = TypeId::of::<M>();
|
||||
|
||||
// Safety: DisplayError is repr(transparent) so DisplayError<M> has the
|
||||
// same layout as the typeid specifies.
|
||||
unsafe { Error::construct(error, type_id, backtrace) }
|
||||
}
|
||||
|
||||
// Takes backtrace as argument rather than capturing it here so that the
|
||||
// user sees one fewer layer of wrapping noise in the backtrace.
|
||||
//
|
||||
@ -424,6 +436,29 @@ where
|
||||
|
||||
impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct DisplayError<M>(M);
|
||||
|
||||
impl<M> Debug for DisplayError<M>
|
||||
where
|
||||
M: Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> Display for DisplayError<M>
|
||||
where
|
||||
M: Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> StdError for DisplayError<M> where M: Display + 'static {}
|
||||
|
||||
impl ErrorImpl<()> {
|
||||
fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
|
||||
unsafe { &*(self.vtable.object)(&self.error) }
|
||||
|
Loading…
x
Reference in New Issue
Block a user