failure/
lib.rs

1//! An experimental new error-handling library. Guide-style introduction
2//! is available [here](https://boats.gitlab.io/failure/).
3//!
4//! The primary items exported by this library are:
5//!
6//! - `Fail`: a new trait for custom error types in Rust.
7//! - `Error`: a wrapper around `Fail` types to make it easy to coalesce them
8//!   at higher levels.
9//!
10//! As a general rule, library authors should create their own error types and
11//! implement `Fail` for them, whereas application authors should primarily
12//! deal with the `Error` type. There are exceptions to this rule, though, in
13//! both directions, and users should do whatever seems most appropriate to
14//! their situation.
15//!
16//! ## Backtraces
17//!
18//! Backtraces are disabled by default. To turn backtraces on, enable
19//! the `backtrace` Cargo feature and set the `RUST_BACKTRACE` environment
20//! variable to a non-zero value (this also enables backtraces for panics).
21//! Use the `RUST_FAILURE_BACKTRACE` variable to enable or disable backtraces
22//! for `failure` specifically.
23#![cfg_attr(not(feature = "std"), no_std)]
24#![deny(missing_docs)]
25#![deny(warnings)]
26#![cfg_attr(feature = "small-error", feature(extern_types, allocator_api))]
27
28macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) }
29macro_rules! without_std { ($($i:item)*) => ($(#[cfg(not(feature = "std"))]$i)*) }
30
31// Re-export libcore using an alias so that the macros can work without
32// requiring `extern crate core` downstream.
33#[doc(hidden)]
34pub extern crate core as _core;
35
36mod as_fail;
37mod backtrace;
38#[cfg(feature = "std")]
39mod box_std;
40mod compat;
41mod context;
42mod result_ext;
43
44use core::any::TypeId;
45use core::fmt::{Debug, Display};
46
47pub use as_fail::AsFail;
48pub use backtrace::Backtrace;
49pub use compat::Compat;
50pub use context::Context;
51pub use result_ext::ResultExt;
52
53#[cfg(feature = "failure_derive")]
54#[allow(unused_imports)]
55#[macro_use]
56extern crate failure_derive;
57
58#[cfg(feature = "failure_derive")]
59#[doc(hidden)]
60pub use failure_derive::*;
61
62with_std! {
63    extern crate core;
64
65    mod sync_failure;
66    pub use sync_failure::SyncFailure;
67
68    mod error;
69
70    use std::error::Error as StdError;
71
72    pub use error::Error;
73
74    /// A common result with an `Error`.
75    pub type Fallible<T> = Result<T, Error>;
76
77    mod macros;
78    mod error_message;
79    pub use error_message::err_msg;
80}
81
82/// The `Fail` trait.
83///
84/// Implementors of this trait are called 'failures'.
85///
86/// All error types should implement `Fail`, which provides a baseline of
87/// functionality that they all share.
88///
89/// `Fail` has no required methods, but it does require that your type
90/// implement several other traits:
91///
92/// - `Display`: to print a user-friendly representation of the error.
93/// - `Debug`: to print a verbose, developer-focused representation of the
94///   error.
95/// - `Send + Sync`: Your error type is required to be safe to transfer to and
96///   reference from another thread
97///
98/// Additionally, all failures must be `'static`. This enables downcasting.
99///
100/// `Fail` provides several methods with default implementations. Two of these
101/// may be appropriate to override depending on the definition of your
102/// particular failure: the `cause` and `backtrace` methods.
103///
104/// The `failure_derive` crate provides a way to derive the `Fail` trait for
105/// your type. Additionally, all types that already implement
106/// `std::error::Error`, and are also `Send`, `Sync`, and `'static`, implement
107/// `Fail` by a blanket impl.
108pub trait Fail: Display + Debug + Send + Sync + 'static {
109    /// Returns the "name" of the error.
110    /// 
111    /// This is typically the type name. Not all errors will implement
112    /// this. This method is expected to be most useful in situations
113    /// where errors need to be reported to external instrumentation systems 
114    /// such as crash reporters.
115    fn name(&self) -> Option<&str> {
116        None
117    }
118
119    /// Returns a reference to the underlying cause of this failure, if it
120    /// is an error that wraps other errors.
121    ///
122    /// Returns `None` if this failure does not have another error as its
123    /// underlying cause. By default, this returns `None`.
124    ///
125    /// This should **never** return a reference to `self`, but only return
126    /// `Some` when it can return a **different** failure. Users may loop
127    /// over the cause chain, and returning `self` would result in an infinite
128    /// loop.
129    fn cause(&self) -> Option<&dyn Fail> {
130        None
131    }
132
133    /// Returns a reference to the `Backtrace` carried by this failure, if it
134    /// carries one.
135    ///
136    /// Returns `None` if this failure does not carry a backtrace. By
137    /// default, this returns `None`.
138    fn backtrace(&self) -> Option<&Backtrace> {
139        None
140    }
141
142    /// Provides context for this failure.
143    ///
144    /// This can provide additional information about this error, appropriate
145    /// to the semantics of the current layer. That is, if you have a
146    /// lower-level error, such as an IO error, you can provide additional context
147    /// about what that error means in the context of your function. This
148    /// gives users of this function more information about what has gone
149    /// wrong.
150    ///
151    /// This takes any type that implements `Display`, as well as
152    /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String`
153    /// or a string literal, or another failure, or some other custom context-carrying
154    /// type.
155    fn context<D>(self, context: D) -> Context<D>
156    where
157        D: Display + Send + Sync + 'static,
158        Self: Sized,
159    {
160        Context::with_err(context, self)
161    }
162
163    /// Wraps this failure in a compatibility wrapper that implements
164    /// `std::error::Error`.
165    ///
166    /// This allows failures  to be compatible with older crates that
167    /// expect types that implement the `Error` trait from `std::error`.
168    fn compat(self) -> Compat<Self>
169    where
170        Self: Sized,
171    {
172        Compat { error: self }
173    }
174
175    #[doc(hidden)]
176    #[deprecated(since = "0.1.2", note = "please use the 'iter_chain()' method instead")]
177    fn causes(&self) -> Causes
178    where
179        Self: Sized,
180    {
181        Causes { fail: Some(self) }
182    }
183
184    #[doc(hidden)]
185    #[deprecated(
186        since = "0.1.2",
187        note = "please use the 'find_root_cause()' method instead"
188    )]
189    fn root_cause(&self) -> &dyn Fail
190    where
191        Self: Sized,
192    {
193        find_root_cause(self)
194    }
195
196    #[doc(hidden)]
197    fn __private_get_type_id__(&self) -> TypeId {
198        TypeId::of::<Self>()
199    }
200}
201
202impl dyn Fail {
203    /// Attempts to downcast this failure to a concrete type by reference.
204    ///
205    /// If the underlying error is not of type `T`, this will return `None`.
206    pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
207        if self.__private_get_type_id__() == TypeId::of::<T>() {
208            unsafe { Some(&*(self as *const dyn Fail as *const T)) }
209        } else {
210            None
211        }
212    }
213
214    /// Attempts to downcast this failure to a concrete type by mutable
215    /// reference.
216    ///
217    /// If the underlying error is not of type `T`, this will return `None`.
218    pub fn downcast_mut<T: Fail>(&mut self) -> Option<&mut T> {
219        if self.__private_get_type_id__() == TypeId::of::<T>() {
220            unsafe { Some(&mut *(self as *mut dyn Fail as *mut T)) }
221        } else {
222            None
223        }
224    }
225
226    /// Returns the "root cause" of this `Fail` - the last value in the
227    /// cause chain which does not return an underlying `cause`.
228    ///
229    /// If this type does not have a cause, `self` is returned, because
230    /// it is its own root cause.
231    ///
232    /// This is equivalent to iterating over `iter_causes()` and taking
233    /// the last item.
234    pub fn find_root_cause(&self) -> &dyn Fail {
235        find_root_cause(self)
236    }
237
238    /// Returns a iterator over the causes of this `Fail` with the cause
239    /// of this fail as the first item and the `root_cause` as the final item.
240    ///
241    /// Use `iter_chain` to also include the fail itself.
242    pub fn iter_causes(&self) -> Causes {
243        Causes { fail: self.cause() }
244    }
245
246    /// Returns a iterator over all fails up the chain from the current
247    /// as the first item up to the `root_cause` as the final item.
248    ///
249    /// This means that the chain also includes the fail itself which
250    /// means that it does *not* start with `cause`.  To skip the outermost
251    /// fail use `iter_causes` instead.
252    pub fn iter_chain(&self) -> Causes {
253        Causes { fail: Some(self) }
254    }
255
256    /// Deprecated alias to `find_root_cause`.
257    #[deprecated(
258        since = "0.1.2",
259        note = "please use the 'find_root_cause()' method instead"
260    )]
261    pub fn root_cause(&self) -> &dyn Fail {
262        find_root_cause(self)
263    }
264
265    /// Deprecated alias to `iter_chain`.
266    #[deprecated(since = "0.1.2", note = "please use the 'iter_chain()' method instead")]
267    pub fn causes(&self) -> Causes {
268        Causes { fail: Some(self) }
269    }
270}
271
272#[cfg(feature = "std")]
273impl<E: StdError + Send + Sync + 'static> Fail for E {}
274
275#[cfg(feature = "std")]
276impl Fail for Box<dyn Fail> {
277    fn cause(&self) -> Option<&dyn Fail> {
278        (**self).cause()
279    }
280
281    fn backtrace(&self) -> Option<&Backtrace> {
282        (**self).backtrace()
283    }
284}
285
286/// A iterator over the causes of a `Fail`
287pub struct Causes<'f> {
288    fail: Option<&'f dyn Fail>,
289}
290
291impl<'f> Iterator for Causes<'f> {
292    type Item = &'f dyn Fail;
293    fn next(&mut self) -> Option<&'f dyn Fail> {
294        self.fail.map(|fail| {
295            self.fail = fail.cause();
296            fail
297        })
298    }
299}
300
301fn find_root_cause(mut fail: &dyn Fail) -> &dyn Fail {
302    while let Some(cause) = fail.cause() {
303        fail = cause;
304    }
305
306    fail
307}