1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/// Defines an error type with a failure context and a kind. /// /// The kind enum needs to be defined explicitly, and has to implement `Fail` already. This macro /// then defines an error type that wraps the kind in a `failure::Context` which makes it carry a /// backtrace and allows nesting errors, and also defines the following methods on the error type: /// /// - `kind()`: Returns a reference to the error kind. /// - `cause()`: Returns the causing error, if any. /// - `backtrace()`: Returns the backtrace of this error (or the cause), if /// `RUST_BACKTRACE` was set. /// /// In addition to this, the following conversions are defined for the error type: /// - `From<ErrorKind>` /// - `From<Context<ErrorKind>>` /// /// ## Example /// /// ```rust /// use failure::Fail; /// # use symbolic_common::derive_failure; /// #[derive(Debug, Fail)] /// enum MyErrorKind { /// #[fail(display = "some")] Something, /// #[fail(display = "else")] Else, /// } /// /// derive_failure!(MyError, MyErrorKind); /// /// fn something() -> Result<(), MyError> { /// Err(MyErrorKind::Something.into()) /// } /// ``` #[macro_export] macro_rules! derive_failure { ($error:ident, $kind:ident $(, $meta:meta)* $(,)?) => { $(#[$meta])* #[derive(Debug)] pub struct $error { inner: ::failure::Context<$kind>, } impl ::failure::Fail for $error { fn cause(&self) -> Option<&dyn ::failure::Fail> { self.inner.cause() } fn backtrace(&self) -> Option<&::failure::Backtrace> { self.inner.backtrace() } } impl ::std::fmt::Display for $error { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { self.inner.fmt(f) } } impl $error { /// Returns the error kind of this error. pub fn kind(&self) -> &$kind { &self.inner.get_context() } } impl From<$kind> for $error { fn from(kind: $kind) -> Self { $error { inner: ::failure::Context::new(kind), } } } impl From<::failure::Context<$kind>> for $error { fn from(inner: ::failure::Context<$kind>) -> Self { $error { inner } } } }; }