]> git.proxmox.com Git - rustc.git/blob - src/vendor/error-chain-0.10.0/src/lib.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / vendor / error-chain-0.10.0 / src / lib.rs
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")]
369 extern crate backtrace;
370
371 use std::error;
372 use std::iter::Iterator;
373 #[cfg(feature = "backtrace")]
374 use std::sync::Arc;
375 use std::fmt;
376
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 = ();
382
383 #[macro_use]
384 mod quick_error;
385 #[macro_use]
386 mod error_chain;
387 #[macro_use]
388 mod quick_main;
389 pub use quick_main::ExitCode;
390 #[cfg(feature = "example_generated")]
391 pub mod example_generated;
392
393 /// Iterator over the error chain using the `Error::cause()` method.
394 pub struct ErrorChainIter<'a>(pub Option<&'a error::Error>);
395
396 impl<'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)]
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())),
418 _ => None,
419 }
420 }
421
422 /// This trait is implemented on all the errors generated by the `error_chain`
423 /// macro.
424 pub 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)]
468 pub struct Display<'a, T: 'a + ?Sized>(&'a T);
469
470 impl<'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)]
491 pub 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
499 impl 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
514 impl 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]
611 macro_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]
643 macro_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)]
657 pub mod mock {
658 error_chain!{}
659 }