drone_mirror_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 backtrace;
37#[cfg(feature = "std")]
38mod box_std;
39mod compat;
40mod context;
41mod result_ext;
42
43use core::any::TypeId;
44use core::fmt::{Debug, Display};
45
46pub use backtrace::Backtrace;
47pub use compat::Compat;
48pub use context::Context;
49pub use result_ext::ResultExt;
50
51#[cfg(feature = "failure_derive")]
52#[allow(unused_imports)]
53#[macro_use]
54extern crate failure_derive;
55
56#[cfg(feature = "failure_derive")]
57#[doc(hidden)]
58pub use failure_derive::*;
59
60with_std! {
61 extern crate core;
62
63 mod sync_failure;
64 pub use sync_failure::SyncFailure;
65
66 mod error;
67
68 use std::error::Error as StdError;
69
70 pub use error::Error;
71
72 /// A common result with an `Error`.
73 pub type Fallible<T> = Result<T, Error>;
74
75 mod macros;
76 mod error_message;
77 pub use error_message::err_msg;
78}
79
80/// The `Fail` trait.
81///
82/// Implementors of this trait are called 'failures'.
83///
84/// All error types should implement `Fail`, which provides a baseline of
85/// functionality that they all share.
86///
87/// `Fail` has no required methods, but it does require that your type
88/// implement several other traits:
89///
90/// - `Display`: to print a user-friendly representation of the error.
91/// - `Debug`: to print a verbose, developer-focused representation of the
92/// error.
93/// - `Send + Sync`: Your error type is required to be safe to transfer to and
94/// reference from another thread
95///
96/// Additionally, all failures must be `'static`. This enables downcasting.
97///
98/// `Fail` provides several methods with default implementations. Two of these
99/// may be appropriate to override depending on the definition of your
100/// particular failure: the `cause` and `backtrace` methods.
101///
102/// The `failure_derive` crate provides a way to derive the `Fail` trait for
103/// your type. Additionally, all types that already implement
104/// `std::error::Error`, and are also `Send`, `Sync`, and `'static`, implement
105/// `Fail` by a blanket impl.
106pub trait Fail: Display + Debug + Send + Sync + 'static {
107 /// Returns a reference to the underlying cause of this failure, if it
108 /// is an error that wraps other errors.
109 ///
110 /// Returns `None` if this failure does not have another error as its
111 /// underlying cause. By default, this returns `None`.
112 ///
113 /// This should **never** return a reference to `self`, but only return
114 /// `Some` when it can return a **different** failure. Users may loop
115 /// over the cause chain, and returning `self` would result in an infinite
116 /// loop.
117 fn cause(&self) -> Option<&Fail> {
118 None
119 }
120
121 /// Returns a reference to the `Backtrace` carried by this failure, if it
122 /// carries one.
123 ///
124 /// Returns `None` if this failure does not carry a backtrace. By
125 /// default, this returns `None`.
126 fn backtrace(&self) -> Option<&Backtrace> {
127 None
128 }
129
130 /// Provides context for this failure.
131 ///
132 /// This can provide additional information about this error, appropriate
133 /// to the semantics of the current layer. That is, if you have a
134 /// lower-level error, such as an IO error, you can provide additional context
135 /// about what that error means in the context of your function. This
136 /// gives users of this function more information about what has gone
137 /// wrong.
138 ///
139 /// This takes any type that implements `Display`, as well as
140 /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String`
141 /// or a string literal, or another failure, or some other custom context-carrying
142 /// type.
143 fn context<D>(self, context: D) -> Context<D>
144 where
145 D: Display + Send + Sync + 'static,
146 Self: Sized,
147 {
148 Context::with_err(context, self)
149 }
150
151 /// Wraps this failure in a compatibility wrapper that implements
152 /// `std::error::Error`.
153 ///
154 /// This allows failures to be compatible with older crates that
155 /// expect types that implement the `Error` trait from `std::error`.
156 fn compat(self) -> Compat<Self>
157 where
158 Self: Sized,
159 {
160 Compat { error: self }
161 }
162
163 #[doc(hidden)]
164 #[deprecated(since = "0.1.2", note = "please use the 'iter_causes()' method instead")]
165 fn causes(&self) -> Causes
166 where
167 Self: Sized,
168 {
169 Causes { fail: Some(self) }
170 }
171
172 #[doc(hidden)]
173 #[deprecated(since = "0.1.2", note = "please use the 'find_root_cause()' method instead")]
174 fn root_cause(&self) -> &Fail
175 where
176 Self: Sized,
177 {
178 find_root_cause(self)
179 }
180
181 #[doc(hidden)]
182 fn __private_get_type_id__(&self) -> TypeId {
183 TypeId::of::<Self>()
184 }
185}
186
187impl Fail {
188 /// Attempts to downcast this failure to a concrete type by reference.
189 ///
190 /// If the underlying error is not of type `T`, this will return `None`.
191 pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
192 if self.__private_get_type_id__() == TypeId::of::<T>() {
193 unsafe { Some(&*(self as *const Fail as *const T)) }
194 } else {
195 None
196 }
197 }
198
199 /// Attempts to downcast this failure to a concrete type by mutable
200 /// reference.
201 ///
202 /// If the underlying error is not of type `T`, this will return `None`.
203 pub fn downcast_mut<T: Fail>(&mut self) -> Option<&mut T> {
204 if self.__private_get_type_id__() == TypeId::of::<T>() {
205 unsafe { Some(&mut *(self as *mut Fail as *mut T)) }
206 } else {
207 None
208 }
209 }
210
211 /// Returns the "root cause" of this `Fail` - the last value in the
212 /// cause chain which does not return an underlying `cause`.
213 ///
214 /// If this type does not have a cause, `self` is returned, because
215 /// it is its own root cause.
216 ///
217 /// This is equivalent to iterating over `iter_causes()` and taking
218 /// the last item.
219 pub fn find_root_cause(&self) -> &Fail {
220 find_root_cause(self)
221 }
222
223 /// Returns a iterator over the causes of this `Fail` with the cause
224 /// of this fail as the first item and the `root_cause` as the final item.
225 ///
226 /// Use `iter_chain` to also include the fail itself.
227 pub fn iter_causes(&self) -> Causes {
228 Causes { fail: self.cause() }
229 }
230
231 /// Returns a iterator over all fails up the chain from the current
232 /// as the first item up to the `root_cause` as the final item.
233 ///
234 /// This means that the chain also includes the fail itself which
235 /// means that it does *not* start with `cause`. To skip the outermost
236 /// fail use `iter_causes` instead.
237 pub fn iter_chain(&self) -> Causes {
238 Causes { fail: Some(self) }
239 }
240
241 /// Deprecated alias to `find_root_cause`.
242 #[deprecated(since = "0.1.2", note = "please use the 'find_root_cause()' method instead")]
243 pub fn root_cause(&self) -> &Fail {
244 find_root_cause(self)
245 }
246
247 /// Deprecated alias to `iter_causes`.
248 #[deprecated(since = "0.1.2", note = "please use the 'iter_chain()' method instead")]
249 pub fn causes(&self) -> Causes {
250 Causes { fail: Some(self) }
251 }
252}
253
254#[cfg(feature = "std")]
255impl<E: StdError + Send + Sync + 'static> Fail for E {}
256
257#[cfg(feature = "std")]
258impl Fail for Box<Fail> {
259 fn cause(&self) -> Option<&Fail> {
260 (**self).cause()
261 }
262
263 fn backtrace(&self) -> Option<&Backtrace> {
264 (**self).backtrace()
265 }
266}
267
268/// A iterator over the causes of a `Fail`
269pub struct Causes<'f> {
270 fail: Option<&'f Fail>,
271}
272
273impl<'f> Iterator for Causes<'f> {
274 type Item = &'f Fail;
275 fn next(&mut self) -> Option<&'f Fail> {
276 self.fail.map(|fail| {
277 self.fail = fail.cause();
278 fail
279 })
280 }
281}
282
283fn find_root_cause(mut fail: &Fail) -> &Fail {
284 while let Some(cause) = fail.cause() {
285 fail = cause;
286 }
287
288 fail
289}