]> git.proxmox.com Git - rustc.git/blame - src/vendor/error-chain/src/lib.rs
New upstream version 1.19.0+dfsg3
[rustc.git] / src / vendor / error-chain / src / lib.rs
CommitLineData
7cac9316
XL
1#![deny(missing_docs)]
2
3//! A library for consistent and reliable error handling
4//!
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.
10//!
11//! ## Quick start
12//!
13//! If you just want to set up your new project with error-chain,
14//! follow the [quickstart.rs] template, and read this [intro]
15//! to error-chain.
16//!
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
19//!
20//! ## Why error chain?
21//!
22//! * error-chain is easy to configure. Handle errors robustly with minimal
23//! effort.
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"
32//! in "error-chain".
33//!
34//! [cause]: https://doc.rust-lang.org/std/error/trait.Error.html#method.cause
35//!
36//! ## Principles of error-chain
37//!
38//! error-chain is based on the following principles:
39//!
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
47//! explicitly.
48//! * Errors implement Send.
49//! * Errors can carry backtraces.
50//!
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.
58//!
59//! This library differs in a few ways from previous error libs:
60//!
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
71//! error.
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
75//! errors.
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.
81//!
82//! To accomplish its goals it makes some tradeoffs:
83//!
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
88//! to match.
89//! * Because the error type contains `std::error::Error + Send + 'static` objects,
90//! it can't implement `PartialEq` for easy comparisons.
91//!
92//! ## Declaring error types
93//!
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.
97//!
98//! Assuming you are using crate-level error types, typically you will
99//! define an `errors` module and inside it call `error_chain!`:
100//!
101//! ```
102//! # #[macro_use] extern crate error_chain;
103//! mod other_error {
104//! error_chain! {}
105//! }
106//!
107//! error_chain! {
108//! // The type defined for this error. These are the conventional
109//! // and recommended names, but they can be arbitrarily chosen.
110//! //
111//! // It is also possible to leave this section out entirely, or
112//! // leave it empty, and these names will be used automatically.
113//! types {
114//! Error, ErrorKind, ResultExt, Result;
115//! }
116//!
117//! // Without the `Result` wrapper:
118//! //
119//! // types {
120//! // Error, ErrorKind, ResultExt;
121//! // }
122//!
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`.
128//! //
129//! // Optionally, some attributes can be added to a variant.
130//! //
131//! // This section can be empty.
132//! links {
133//! Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)];
134//! }
135//!
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.
141//! //
142//! // Optionally, some attributes can be added to a variant.
143//! //
144//! // This section can be empty.
145//! foreign_links {
146//! Fmt(::std::fmt::Error);
147//! Io(::std::io::Error) #[cfg(unix)];
148//! }
149//!
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.
153//! errors {
154//! InvalidToolchainName(t: String) {
155//! description("invalid toolchain name")
156//! display("invalid toolchain name: '{}'", t)
157//! }
158//! }
159//! }
160//!
161//! # fn main() {}
162//! ```
163//!
164//! Each section, `types`, `links`, `foreign_links`, and `errors` may
165//! be omitted if it is empty.
166//!
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.
171//!
172//! ## Returning new errors
173//!
174//! Introducing new error chains, with a string message:
175//!
176//! ```
177//! # #[macro_use] extern crate error_chain;
178//! # fn main() {}
179//! # error_chain! {}
180//! fn foo() -> Result<()> {
181//! Err("foo error!".into())
182//! }
183//! ```
184//!
185//! Introducing new error chains, with an `ErrorKind`:
186//!
187//! ```
188//! # #[macro_use] extern crate error_chain;
189//! # fn main() {}
190//! error_chain! {
191//! errors { FooError }
192//! }
193//!
194//! fn foo() -> Result<()> {
195//! Err(ErrorKind::FooError.into())
196//! }
197//! ```
198//!
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
204//! `Error`.
205//!
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:
210//!
211//! ```
212//! # #[macro_use] extern crate error_chain;
213//! # fn main() {}
214//! # error_chain! { errors { FooError } }
215//! fn foo() -> Result<()> {
216//! Ok(try!(Err(ErrorKind::FooError)))
217//! }
218//!
219//! fn bar() -> Result<()> {
220//! Ok(try!(Err("bogus!")))
221//! }
222//! ```
223//!
224//! ## The `bail!` macro
225//!
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:
230//!
231//! ```
232//! # #[macro_use] extern crate error_chain;
233//! # fn main() {}
234//! # error_chain! { errors { FooError } }
235//! fn foo() -> Result<()> {
236//! if true {
237//! bail!(ErrorKind::FooError);
238//! } else {
239//! Ok(())
240//! }
241//! }
242//!
243//! fn bar() -> Result<()> {
244//! if true {
245//! bail!("bogus!");
246//! } else {
247//! Ok(())
248//! }
249//! }
250//! ```
251//!
252//! ## Chaining errors
253//!
254//! To extend the error chain:
255//!
256//! ```
257//! # #[macro_use] extern crate error_chain;
258//! # fn main() {}
259//! # error_chain! {}
260//! # fn do_something() -> Result<()> { unimplemented!() }
261//! # fn test() -> Result<()> {
262//! let res: Result<()> = do_something().chain_err(|| "something went wrong");
263//! # Ok(())
264//! # }
265//! ```
266//!
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.
273//!
274//! ## Matching errors
275//!
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:
279//!
280//! ```
281//! # #[macro_use] extern crate error_chain;
282//! # fn main() {
283//! error_chain! {
284//! errors {
285//! InvalidToolchainName(t: String) {
286//! description("invalid toolchain name")
287//! display("invalid toolchain name: '{}'", t)
288//! }
289//! }
290//! }
291//!
292//! match Error::from("error!") {
293//! Error(ErrorKind::InvalidToolchainName(_), _) => { }
294//! Error(ErrorKind::Msg(_), _) => { }
295//! }
296//! # }
297//! ```
298//!
299//! Chained errors are also matched with (relatively) compact syntax
300//!
301//! ```
302//! # #[macro_use] extern crate error_chain;
303//! mod utils {
304//! error_chain! {
305//! errors {
306//! BadStuff {
307//! description("bad stuff")
308//! }
309//! }
310//! }
311//! }
312//!
313//! mod app {
314//! error_chain! {
315//! links {
316//! Utils(::utils::Error, ::utils::ErrorKind);
317//! }
318//! }
319//! }
320//!
321//!
322//! # fn main() {
323//! match app::Error::from("error!") {
324//! app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { }
325//! _ => { }
326//! }
327//! # }
328//! ```
329//!
330//! ## Foreign links
331//!
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.
337//!
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
348//! original error.
349//!
350//! ## Backtraces
351//!
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.
357//!
358//! Backtrace generation can be disabled by turning off the `backtrace` feature.
359//!
360//! ## Iteration
361//!
362//! The `iter` method returns an iterator over the chain of error boxes.
363//!
364//! [error-type]: https://github.com/DanielKeep/rust-error-type
365//! [quick-error]: https://github.com/tailhook/quick-error
366
367
368#[cfg(feature = "backtrace")]
369extern crate backtrace;
370
371use std::error;
372use std::iter::Iterator;
373#[cfg(feature = "backtrace")]
374use std::sync::Arc;
375use std::fmt;
376
377#[cfg(feature = "backtrace")]
378pub use backtrace::Backtrace;
379#[cfg(not(feature = "backtrace"))]
380/// Dummy type used when the `backtrace` feature is disabled.
381pub type Backtrace = ();
382
383#[macro_use]
384mod quick_error;
385#[macro_use]
386mod error_chain;
387#[macro_use]
388mod quick_main;
389pub use quick_main::ExitCode;
390#[cfg(feature = "example_generated")]
391pub mod example_generated;
392
393/// Iterator over the error chain using the `Error::cause()` method.
394pub struct ErrorChainIter<'a>(pub Option<&'a error::Error>);
395
396impl<'a> Iterator for ErrorChainIter<'a> {
397 type Item = &'a error::Error;
398
399 fn next<'b>(&'b mut self) -> Option<&'a error::Error> {
400 match self.0.take() {
401 Some(e) => {
402 self.0 = e.cause();
403 Some(e)
404 }
405 None => None,
406 }
407 }
408}
409
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")]
414#[doc(hidden)]
415pub 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())),
418 _ => None,
419 }
420}
421
422/// This trait is implemented on all the errors generated by the `error_chain`
423/// macro.
424pub trait ChainedError: error::Error + Send + 'static {
425 /// Associated kind type.
426 type ErrorKind;
427
428 /// Constructs an error from a kind, and generates a backtrace.
429 fn from_kind(kind: Self::ErrorKind) -> Self where Self: Sized;
430
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
433 where Self: Sized,
434 E: ::std::error::Error + Send + 'static,
435 K: Into<Self::ErrorKind>;
436
437 /// Returns the kind of the error.
438 fn kind(&self) -> &Self::ErrorKind;
439
440 /// Iterates over the error chain.
441 fn iter(&self) -> ErrorChainIter;
442
443 /// Returns the backtrace associated with this error.
444 fn backtrace(&self) -> Option<&Backtrace>;
445
446 /// Returns an object which implements `Display` for printing the full
447 /// context of this error.
448 ///
449 /// The full cause chain and backtrace, if present, will be printed.
450 fn display<'a>(&'a self) -> Display<'a, Self> {
451 Display(self)
452 }
453
454 /// Creates an error from its parts.
455 #[doc(hidden)]
456 fn new(kind: Self::ErrorKind, state: State) -> Self where Self: Sized;
457
458 /// Returns the first known backtrace, either from its State or from one
459 /// of the errors from `foreign_links`.
460 #[cfg(feature = "backtrace")]
461 #[doc(hidden)]
462 fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<Arc<Backtrace>>
463 where Self: Sized;
464}
465
466/// A struct which formats an error for output.
467#[derive(Debug)]
468pub struct Display<'a, T: 'a + ?Sized>(&'a T);
469
470impl<'a, T> fmt::Display for Display<'a, T>
471 where T: ChainedError
472{
473 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
474 try!(writeln!(fmt, "Error: {}", self.0));
475
476 for e in self.0.iter().skip(1) {
477 try!(writeln!(fmt, "Caused by: {}", e));
478 }
479
480 if let Some(backtrace) = self.0.backtrace() {
481 try!(writeln!(fmt, "{:?}", backtrace));
482 }
483
484 Ok(())
485 }
486}
487
488/// Common state between errors.
489#[derive(Debug)]
490#[doc(hidden)]
491pub struct State {
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>>,
497}
498
499impl Default for State {
500 #[cfg(feature = "backtrace")]
501 fn default() -> State {
502 State {
503 next_error: None,
504 backtrace: make_backtrace(),
505 }
506 }
507
508 #[cfg(not(feature = "backtrace"))]
509 fn default() -> State {
510 State { next_error: None }
511 }
512}
513
514impl State {
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);
519 State {
520 next_error: Some(e),
521 backtrace: backtrace,
522 }
523 }
524
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) }
529 }
530
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)
535 }
536
537 /// Returns the inner backtrace if present.
538 #[cfg(not(feature = "backtrace"))]
539 pub fn backtrace(&self) -> Option<&Backtrace> {
540 None
541 }
542}
543
544/// Exits a function early with an error
545///
546/// The `bail!` macro provides an easy way to exit a function.
547/// `bail!(expr)` is equivalent to writing.
548///
549/// ```
550/// # #[macro_use] extern crate error_chain;
551/// # error_chain! { }
552/// # fn main() { }
553/// # fn foo() -> Result<()> {
554/// # let expr = "";
555/// return Err(expr.into());
556/// # }
557/// ```
558///
559/// And as shorthand it takes a formatting string a la `println!`:
560///
561/// ```
562/// # #[macro_use] extern crate error_chain;
563/// # error_chain! { }
564/// # fn main() { }
565/// # fn foo() -> Result<()> {
566/// # let n = 0;
567/// bail!("bad number: {}", n);
568/// # }
569/// ```
570///
571/// # Examples
572///
573/// Bailing on a custom error:
574///
575/// ```
576/// # #[macro_use] extern crate error_chain;
577/// # fn main() {}
578/// error_chain! {
579/// errors { FooError }
580/// }
581///
582/// fn foo() -> Result<()> {
583/// if bad_condition() {
584/// bail!(ErrorKind::FooError);
585/// }
586///
587/// Ok(())
588/// }
589///
590/// # fn bad_condition() -> bool { true }
591/// ```
592///
593/// Bailing on a formatted string:
594///
595/// ```
596/// # #[macro_use] extern crate error_chain;
597/// # fn main() {}
598/// error_chain! { }
599///
600/// fn foo() -> Result<()> {
601/// if let Some(bad_num) = bad_condition() {
602/// bail!("so bad: {}", bad_num);
603/// }
604///
605/// Ok(())
606/// }
607///
608/// # fn bad_condition() -> Option<i8> { None }
609/// ```
610#[macro_export]
611macro_rules! bail {
612 ($e:expr) => {
613 return Err($e.into());
614 };
615 ($fmt:expr, $($arg:tt)+) => {
616 return Err(format!($fmt, $($arg)+).into());
617 };
618}
619
620/// Exits a function early with an error if the condition is not satisfied
621///
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.
624///
625/// As an example, `ensure!(condition, "error code: {}", errcode)` is equivalent to
626///
627/// ```
628/// # #[macro_use] extern crate error_chain;
629/// # error_chain! { }
630/// # fn main() { }
631/// # fn foo() -> Result<()> {
632/// # let errcode = 0u8;
633/// # let condition = true;
634/// if !condition {
635/// bail!("error code: {}", errcode);
636/// }
637/// # Ok(())
638/// # }
639/// ```
640///
641/// See documentation for `bail!` macro for further details.
642#[macro_export]
643macro_rules! ensure {
644 ($cond:expr, $e:expr) => {
645 if !($cond) {
646 bail!($e);
647 }
648 };
649 ($cond:expr, $fmt:expr, $($arg:tt)+) => {
650 if !($cond) {
651 bail!($fmt, $($arg)+);
652 }
653 };
654}
655
656#[doc(hidden)]
657pub mod mock {
658 error_chain!{}
659}