3 //! A library for consistent and reliable error handling
5 //! error-chain makes it easy to take full advantage of Rust's
6 //! powerful error handling features without the overhead of
7 //! maintaining boilerplate error types and conversions. It implements
8 //! an opinionated strategy for defining your own error types, as well
9 //! as conversions from others' error types.
13 //! If you just want to set up your new project with error-chain,
14 //! follow the [quickstart.rs] template, and read this [intro]
17 //! [quickstart.rs]: https://github.com/brson/error-chain/blob/master/examples/quickstart.rs
18 //! [intro]: http://brson.github.io/2016/11/30/starting-with-error-chain
20 //! ## Why error chain?
22 //! * error-chain is easy to configure. Handle errors robustly with minimal
24 //! * Basic error handling requires no maintenance of custom error types
25 //! nor the `From` conversions that make `?` work.
26 //! * error-chain scales from simple error handling strategies to more
27 //! rigorous. Return formatted strings for simple errors, only
28 //! introducing error variants and their strong typing as needed for
29 //! advanced error recovery.
30 //! * error-chain makes it trivial to correctly manage the [cause] of
31 //! the errors generated by your own code. This is the "chaining"
34 //! [cause]: https://doc.rust-lang.org/std/error/trait.Error.html#method.cause
36 //! ## Principles of error-chain
38 //! error-chain is based on the following principles:
40 //! * No error should ever be discarded. This library primarily
41 //! makes it easy to "chain" errors with the `chain_err` method.
42 //! * Introducing new errors is trivial. Simple errors can be introduced
43 //! at the error site with just a string.
44 //! * Handling errors is possible with pattern matching.
45 //! * Conversions between error types are done in an automatic and
46 //! consistent way - `From` conversion behavior is never specified
48 //! * Errors implement Send.
49 //! * Errors can carry backtraces.
51 //! Similar to other libraries like [error-type] and [quick-error],
52 //! this library introduces the error chaining mechanism originally
53 //! employed by Cargo. The `error_chain!` macro declares the types
54 //! and implementation boilerplate necessary for fulfilling a
55 //! particular error-handling strategy. Most importantly it defines a
56 //! custom error type (called `Error` by convention) and the `From`
57 //! conversions that let the `try!` macro and `?` operator work.
59 //! This library differs in a few ways from previous error libs:
61 //! * Instead of defining the custom `Error` type as an enum, it is a
62 //! struct containing an `ErrorKind` (which defines the
63 //! `description` and `display` methods for the error), an opaque,
64 //! optional, boxed `std::error::Error + Send + 'static` object
65 //! (which defines the `cause`, and establishes the links in the
66 //! error chain), and a `Backtrace`.
67 //! * The macro also defines a `ResultExt` trait that defines a
68 //! `chain_err` method. This method on all `std::error::Error + Send + 'static`
69 //! types extends the error chain by boxing the current
70 //! error into an opaque object and putting it inside a new concrete
72 //! * It provides automatic `From` conversions between other error types
73 //! defined by the `error_chain!` that preserve type information,
74 //! and facilitate seamless error composition and matching of composed
76 //! * It provides automatic `From` conversions between any other error
77 //! type that hides the type of the other error in the `cause` box.
78 //! * If `RUST_BACKTRACE` is enabled, it collects a single backtrace at
79 //! the earliest opportunity and propagates it down the stack through
80 //! `From` and `ResultExt` conversions.
82 //! To accomplish its goals it makes some tradeoffs:
84 //! * The split between the `Error` and `ErrorKind` types can make it
85 //! slightly more cumbersome to instantiate new (unchained) errors,
86 //! requiring an `Into` or `From` conversion; as well as slightly
87 //! more cumbersome to match on errors with another layer of types
89 //! * Because the error type contains `std::error::Error + Send + 'static` objects,
90 //! it can't implement `PartialEq` for easy comparisons.
92 //! ## Declaring error types
94 //! Generally, you define one family of error types per crate, though
95 //! it's also perfectly fine to define error types on a finer-grained
96 //! basis, such as per module.
98 //! Assuming you are using crate-level error types, typically you will
99 //! define an `errors` module and inside it call `error_chain!`:
102 //! # #[macro_use] extern crate error_chain;
103 //! mod other_error {
108 //! // The type defined for this error. These are the conventional
109 //! // and recommended names, but they can be arbitrarily chosen.
111 //! // It is also possible to leave this section out entirely, or
112 //! // leave it empty, and these names will be used automatically.
114 //! Error, ErrorKind, ResultExt, Result;
117 //! // Without the `Result` wrapper:
120 //! // Error, ErrorKind, ResultExt;
123 //! // Automatic conversions between this error chain and other
124 //! // error chains. In this case, it will e.g. generate an
125 //! // `ErrorKind` variant called `Another` which in turn contains
126 //! // the `other_error::ErrorKind`, with conversions from
127 //! // `other_error::Error`.
129 //! // Optionally, some attributes can be added to a variant.
131 //! // This section can be empty.
133 //! Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)];
136 //! // Automatic conversions between this error chain and other
137 //! // error types not defined by the `error_chain!`. These will be
138 //! // wrapped in a new error with, in the first case, the
139 //! // `ErrorKind::Fmt` variant. The description and cause will
140 //! // forward to the description and cause of the original error.
142 //! // Optionally, some attributes can be added to a variant.
144 //! // This section can be empty.
146 //! Fmt(::std::fmt::Error);
147 //! Io(::std::io::Error) #[cfg(unix)];
150 //! // Define additional `ErrorKind` variants. The syntax here is
151 //! // the same as `quick_error!`, but the `from()` and `cause()`
152 //! // syntax is not supported.
154 //! InvalidToolchainName(t: String) {
155 //! description("invalid toolchain name")
156 //! display("invalid toolchain name: '{}'", t)
164 //! Each section, `types`, `links`, `foreign_links`, and `errors` may
165 //! be omitted if it is empty.
167 //! This populates the module with a number of definitions,
168 //! the most important of which are the `Error` type
169 //! and the `ErrorKind` type. An example of generated code can be found in the
170 //! [example_generated](example_generated) module.
172 //! ## Returning new errors
174 //! Introducing new error chains, with a string message:
177 //! # #[macro_use] extern crate error_chain;
179 //! # error_chain! {}
180 //! fn foo() -> Result<()> {
181 //! Err("foo error!".into())
185 //! Introducing new error chains, with an `ErrorKind`:
188 //! # #[macro_use] extern crate error_chain;
191 //! errors { FooError }
194 //! fn foo() -> Result<()> {
195 //! Err(ErrorKind::FooError.into())
199 //! Note that the return type is the typedef `Result`, which is
200 //! defined by the macro as `pub type Result<T> =
201 //! ::std::result::Result<T, Error>`. Note that in both cases
202 //! `.into()` is called to convert a type into the `Error` type; both
203 //! strings and `ErrorKind` have `From` conversions to turn them into
206 //! When the error is emitted inside a `try!` macro or behind the
207 //! `?` operator, the explicit conversion isn't needed; `try!` will
208 //! automatically convert `Err(ErrorKind)` to `Err(Error)`. So the
209 //! below is equivalent to the previous:
212 //! # #[macro_use] extern crate error_chain;
214 //! # error_chain! { errors { FooError } }
215 //! fn foo() -> Result<()> {
216 //! Ok(try!(Err(ErrorKind::FooError)))
219 //! fn bar() -> Result<()> {
220 //! Ok(try!(Err("bogus!")))
224 //! ## The `bail!` macro
226 //! The above method of introducing new errors works but is a little
227 //! verbose. Instead we can use the `bail!` macro, which, much like `try!`
228 //! and `?`, performs an early return with conversions. With `bail!` the
229 //! previous examples look like:
232 //! # #[macro_use] extern crate error_chain;
234 //! # error_chain! { errors { FooError } }
235 //! fn foo() -> Result<()> {
237 //! bail!(ErrorKind::FooError);
243 //! fn bar() -> Result<()> {
252 //! ## Chaining errors
254 //! To extend the error chain:
257 //! # #[macro_use] extern crate error_chain;
259 //! # error_chain! {}
260 //! # fn do_something() -> Result<()> { unimplemented!() }
261 //! # fn test() -> Result<()> {
262 //! let res: Result<()> = do_something().chain_err(|| "something went wrong");
267 //! `chain_err` can be called on any `Result` type where the contained
268 //! error type implements `std::error::Error + Send + 'static`. If
269 //! the `Result` is an `Err` then `chain_err` evaluates the closure,
270 //! which returns *some type that can be converted to `ErrorKind`*,
271 //! boxes the original error to store as the cause, then returns a new
272 //! error containing the original error.
274 //! ## Matching errors
276 //! error-chain error variants are matched with simple patterns.
277 //! `Error` is a tuple struct and its first field is the `ErrorKind`,
278 //! making dispatching on error kinds relatively compact:
281 //! # #[macro_use] extern crate error_chain;
285 //! InvalidToolchainName(t: String) {
286 //! description("invalid toolchain name")
287 //! display("invalid toolchain name: '{}'", t)
292 //! match Error::from("error!") {
293 //! Error(ErrorKind::InvalidToolchainName(_), _) => { }
294 //! Error(ErrorKind::Msg(_), _) => { }
299 //! Chained errors are also matched with (relatively) compact syntax
302 //! # #[macro_use] extern crate error_chain;
307 //! description("bad stuff")
316 //! Utils(::utils::Error, ::utils::ErrorKind);
323 //! match app::Error::from("error!") {
324 //! app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { }
332 //! Errors that do not conform to the same conventions as this library
333 //! can still be included in the error chain. They are considered "foreign
334 //! errors", and are declared using the `foreign_links` block of the
335 //! `error_chain!` macro. `Error`s are automatically created from
336 //! foreign errors by the `try!` macro.
338 //! Foreign links and regular links have one crucial difference:
339 //! `From` conversions for regular links *do not introduce a new error
340 //! into the error chain*, while conversions for foreign links *always
341 //! introduce a new error into the error chain*. So for the example
342 //! above all errors deriving from the `temp::Error` type will be
343 //! presented to the user as a new `ErrorKind::Temp` variant, and the
344 //! cause will be the original `temp::Error` error. In contrast, when
345 //! `rustup_utils::Error` is converted to `Error` the two `ErrorKind`s
346 //! are converted between each other to create a new `Error` but the
347 //! old error is discarded; there is no "cause" created from the
352 //! If the `RUST_BACKTRACE` environment variable is set to anything
353 //! but ``0``, the earliest non-foreign error to be generated creates
354 //! a single backtrace, which is passed through all `From` conversions
355 //! and `chain_err` invocations of compatible types. To read the
356 //! backtrace just call the `backtrace()` method.
358 //! Backtrace generation can be disabled by turning off the `backtrace` feature.
362 //! The `iter` method returns an iterator over the chain of error boxes.
364 //! [error-type]: https://github.com/DanielKeep/rust-error-type
365 //! [quick-error]: https://github.com/tailhook/quick-error
368 #[cfg(feature = "backtrace")]
369 extern crate backtrace
;
372 use std
::iter
::Iterator
;
373 #[cfg(feature = "backtrace")]
377 #[cfg(feature = "backtrace")]
378 pub use backtrace
::Backtrace
;
379 #[cfg(not(feature = "backtrace"))]
380 /// Dummy type used when the `backtrace` feature is disabled.
381 pub type Backtrace
= ();
389 pub use quick_main
::ExitCode
;
390 #[cfg(feature = "example_generated")]
391 pub mod example_generated
;
393 /// Iterator over the error chain using the `Error::cause()` method.
394 pub struct ErrorChainIter
<'a
>(pub Option
<&'a error
::Error
>);
396 impl<'a
> Iterator
for ErrorChainIter
<'a
> {
397 type Item
= &'a error
::Error
;
399 fn next
<'b
>(&'b
mut self) -> Option
<&'a error
::Error
> {
400 match self.0.take() {
410 /// Returns a backtrace of the current call stack if `RUST_BACKTRACE`
411 /// is set to anything but ``0``, and `None` otherwise. This is used
412 /// in the generated error implementations.
413 #[cfg(feature = "backtrace")]
415 pub fn make_backtrace() -> Option
<Arc
<Backtrace
>> {
416 match std
::env
::var_os("RUST_BACKTRACE") {
417 Some(ref val
) if val
!= "0" => Some(Arc
::new(Backtrace
::new())),
422 /// This trait is implemented on all the errors generated by the `error_chain`
424 pub trait ChainedError
: error
::Error
+ Send
+ '
static {
425 /// Associated kind type.
428 /// Constructs an error from a kind, and generates a backtrace.
429 fn from_kind(kind
: Self::ErrorKind
) -> Self where Self: Sized
;
431 /// Constructs a chained error from another error and a kind, and generates a backtrace.
432 fn with_chain
<E
, K
>(error
: E
, kind
: K
) -> Self
434 E
: ::std
::error
::Error
+ Send
+ '
static,
435 K
: Into
<Self::ErrorKind
>;
437 /// Returns the kind of the error.
438 fn kind(&self) -> &Self::ErrorKind
;
440 /// Iterates over the error chain.
441 fn iter(&self) -> ErrorChainIter
;
443 /// Returns the backtrace associated with this error.
444 fn backtrace(&self) -> Option
<&Backtrace
>;
446 /// Returns an object which implements `Display` for printing the full
447 /// context of this error.
449 /// The full cause chain and backtrace, if present, will be printed.
450 fn display
<'a
>(&'a
self) -> Display
<'a
, Self> {
454 /// Creates an error from its parts.
456 fn new(kind
: Self::ErrorKind
, state
: State
) -> Self where Self: Sized
;
458 /// Returns the first known backtrace, either from its State or from one
459 /// of the errors from `foreign_links`.
460 #[cfg(feature = "backtrace")]
462 fn extract_backtrace(e
: &(error
::Error
+ Send
+ '
static)) -> Option
<Arc
<Backtrace
>>
466 /// A struct which formats an error for output.
468 pub struct Display
<'a
, T
: 'a
+ ?Sized
>(&'a T
);
470 impl<'a
, T
> fmt
::Display
for Display
<'a
, T
>
471 where T
: ChainedError
473 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
474 try
!(writeln
!(fmt
, "Error: {}", self.0));
476 for e
in self.0.iter
().skip(1) {
477 try
!(writeln
!(fmt
, "Caused by: {}", e
));
480 if let Some(backtrace
) = self.0.backtrace() {
481 try
!(writeln
!(fmt
, "{:?}", backtrace
));
488 /// Common state between errors.
492 /// Next error in the error chain.
493 pub next_error
: Option
<Box
<error
::Error
+ Send
>>,
494 /// Backtrace for the current error.
495 #[cfg(feature = "backtrace")]
496 pub backtrace
: Option
<Arc
<Backtrace
>>,
499 impl Default
for State
{
500 #[cfg(feature = "backtrace")]
501 fn default() -> State
{
504 backtrace
: make_backtrace(),
508 #[cfg(not(feature = "backtrace"))]
509 fn default() -> State
{
510 State { next_error: None }
515 /// Creates a new State type
516 #[cfg(feature = "backtrace")]
517 pub fn new
<CE
: ChainedError
>(e
: Box
<error
::Error
+ Send
>) -> State
{
518 let backtrace
= CE
::extract_backtrace(&*e
).or_else(make_backtrace
);
521 backtrace
: backtrace
,
525 /// Creates a new State type
526 #[cfg(not(feature = "backtrace"))]
527 pub fn new
<CE
: ChainedError
>(e
: Box
<error
::Error
+ Send
>) -> State
{
528 State { next_error: Some(e) }
531 /// Returns the inner backtrace if present.
532 #[cfg(feature = "backtrace")]
533 pub fn backtrace(&self) -> Option
<&Backtrace
> {
534 self.backtrace
.as_ref().map(|v
| &**v
)
537 /// Returns the inner backtrace if present.
538 #[cfg(not(feature = "backtrace"))]
539 pub fn backtrace(&self) -> Option
<&Backtrace
> {
544 /// Exits a function early with an error
546 /// The `bail!` macro provides an easy way to exit a function.
547 /// `bail!(expr)` is equivalent to writing.
550 /// # #[macro_use] extern crate error_chain;
551 /// # error_chain! { }
553 /// # fn foo() -> Result<()> {
555 /// return Err(expr.into());
559 /// And as shorthand it takes a formatting string a la `println!`:
562 /// # #[macro_use] extern crate error_chain;
563 /// # error_chain! { }
565 /// # fn foo() -> Result<()> {
567 /// bail!("bad number: {}", n);
573 /// Bailing on a custom error:
576 /// # #[macro_use] extern crate error_chain;
579 /// errors { FooError }
582 /// fn foo() -> Result<()> {
583 /// if bad_condition() {
584 /// bail!(ErrorKind::FooError);
590 /// # fn bad_condition() -> bool { true }
593 /// Bailing on a formatted string:
596 /// # #[macro_use] extern crate error_chain;
600 /// fn foo() -> Result<()> {
601 /// if let Some(bad_num) = bad_condition() {
602 /// bail!("so bad: {}", bad_num);
608 /// # fn bad_condition() -> Option<i8> { None }
613 return Err($e
.into());
615 ($fmt
:expr
, $
($arg
:tt
)+) => {
616 return Err(format
!($fmt
, $
($arg
)+).into());
620 /// Exits a function early with an error if the condition is not satisfied
622 /// The `ensure!` macro is a convenience helper that provides a way to exit
623 /// a function with an error if the given condition fails.
625 /// As an example, `ensure!(condition, "error code: {}", errcode)` is equivalent to
628 /// # #[macro_use] extern crate error_chain;
629 /// # error_chain! { }
631 /// # fn foo() -> Result<()> {
632 /// # let errcode = 0u8;
633 /// # let condition = true;
635 /// bail!("error code: {}", errcode);
641 /// See documentation for `bail!` macro for further details.
643 macro_rules
! ensure
{
644 ($cond
:expr
, $e
:expr
) => {
649 ($cond
:expr
, $fmt
:expr
, $
($arg
:tt
)+) => {
651 bail
!($fmt
, $
($arg
)+);