/rust/registry/src/index.crates.io-1949cf8c6b5b557f/error-chain-0.12.4/src/lib.rs
Line | Count | Source |
1 | | #![deny(missing_docs)] |
2 | | #![doc(html_root_url = "https://docs.rs/error-chain/0.12.4")] |
3 | | |
4 | | //! A library for consistent and reliable error handling |
5 | | //! |
6 | | //! error-chain makes it easy to take full advantage of Rust's |
7 | | //! powerful error handling features without the overhead of |
8 | | //! maintaining boilerplate error types and conversions. It implements |
9 | | //! an opinionated strategy for defining your own error types, as well |
10 | | //! as conversions from others' error types. |
11 | | //! |
12 | | //! ## Quick start |
13 | | //! |
14 | | //! If you just want to set up your new project with error-chain, |
15 | | //! follow the [quickstart.rs] template, and read this [intro] |
16 | | //! to error-chain. |
17 | | //! |
18 | | //! [quickstart.rs]: https://github.com/rust-lang-nursery/error-chain/blob/master/examples/quickstart.rs |
19 | | //! [intro]: http://brson.github.io/2016/11/30/starting-with-error-chain |
20 | | //! |
21 | | //! ## Why error chain? |
22 | | //! |
23 | | //! * error-chain is easy to configure. Handle errors robustly with minimal |
24 | | //! effort. |
25 | | //! * Basic error handling requires no maintenance of custom error types |
26 | | //! nor the [`From`] conversions that make `?` work. |
27 | | //! * error-chain scales from simple error handling strategies to more |
28 | | //! rigorous. Return formatted strings for simple errors, only |
29 | | //! introducing error variants and their strong typing as needed for |
30 | | //! advanced error recovery. |
31 | | //! * error-chain makes it trivial to correctly manage the [cause] of |
32 | | //! the errors generated by your own code. This is the "chaining" |
33 | | //! in "error-chain". |
34 | | //! |
35 | | //! [cause]: https://doc.rust-lang.org/std/error/trait.Error.html#method.cause |
36 | | //! |
37 | | //! ## Principles of error-chain |
38 | | //! |
39 | | //! error-chain is based on the following principles: |
40 | | //! |
41 | | //! * No error should ever be discarded. This library primarily |
42 | | //! makes it easy to "chain" errors with the [`chain_err`] method. |
43 | | //! * Introducing new errors is trivial. Simple errors can be introduced |
44 | | //! at the error site with just a string. |
45 | | //! * Handling errors is possible with pattern matching. |
46 | | //! * Conversions between error types are done in an automatic and |
47 | | //! consistent way - [`From`] conversion behavior is never specified |
48 | | //! explicitly. |
49 | | //! * Errors implement [`Send`]. |
50 | | //! * Errors can carry backtraces. |
51 | | //! |
52 | | //! Similar to other libraries like [error-type] and [quick-error], |
53 | | //! this library introduces the error chaining mechanism originally |
54 | | //! employed by Cargo. The [`error_chain!`] macro declares the types |
55 | | //! and implementation boilerplate necessary for fulfilling a |
56 | | //! particular error-handling strategy. Most importantly it defines a |
57 | | //! custom error type (called [`Error`] by convention) and the [`From`] |
58 | | //! conversions that let the `?` operator work. |
59 | | //! |
60 | | //! This library differs in a few ways from previous error libs: |
61 | | //! |
62 | | //! * Instead of defining the custom [`Error`] type as an enum, it is a |
63 | | //! struct containing an [`ErrorKind`][] (which defines the |
64 | | //! [`description`] and [`display_chain`] methods for the error), an opaque, |
65 | | //! optional, boxed [`std::error::Error`]` + `[`Send`]` + 'static` object |
66 | | //! (which defines the [`cause`], and establishes the links in the |
67 | | //! error chain), and a [`Backtrace`]. |
68 | | //! * The macro also defines a [`ResultExt`] trait that defines a |
69 | | //! [`chain_err`] method. This method on all [`std::error::Error`]` + `[`Send`]` + 'static` |
70 | | //! types extends the error chain by boxing the current |
71 | | //! error into an opaque object and putting it inside a new concrete |
72 | | //! error. |
73 | | //! * It provides automatic [`From`] conversions between other error types |
74 | | //! defined by the [`error_chain!`] that preserve type information, |
75 | | //! and facilitate seamless error composition and matching of composed |
76 | | //! errors. |
77 | | //! * It provides automatic [`From`] conversions between any other error |
78 | | //! type that hides the type of the other error in the [`cause`] box. |
79 | | //! * If `RUST_BACKTRACE` is enabled, it collects a single backtrace at |
80 | | //! the earliest opportunity and propagates it down the stack through |
81 | | //! [`From`] and [`ResultExt`] conversions. |
82 | | //! |
83 | | //! To accomplish its goals it makes some tradeoffs: |
84 | | //! |
85 | | //! * The split between the [`Error`] and [`ErrorKind`] types can make it |
86 | | //! slightly more cumbersome to instantiate new (unchained) errors, |
87 | | //! requiring an [`Into`] or [`From`] conversion; as well as slightly |
88 | | //! more cumbersome to match on errors with another layer of types |
89 | | //! to match. |
90 | | //! * Because the error type contains [`std::error::Error`]` + `[`Send`]` + 'static` objects, |
91 | | //! it can't implement [`PartialEq`] for easy comparisons. |
92 | | //! |
93 | | //! ## Declaring error types |
94 | | //! |
95 | | //! Generally, you define one family of error types per crate, though |
96 | | //! it's also perfectly fine to define error types on a finer-grained |
97 | | //! basis, such as per module. |
98 | | //! |
99 | | //! Assuming you are using crate-level error types, typically you will |
100 | | //! define an `errors` module and inside it call [`error_chain!`]: |
101 | | //! |
102 | | //! ``` |
103 | | //! # #[macro_use] extern crate error_chain; |
104 | | //! mod other_error { |
105 | | //! error_chain! {} |
106 | | //! } |
107 | | //! |
108 | | //! error_chain! { |
109 | | //! // The type defined for this error. These are the conventional |
110 | | //! // and recommended names, but they can be arbitrarily chosen. |
111 | | //! // |
112 | | //! // It is also possible to leave this section out entirely, or |
113 | | //! // leave it empty, and these names will be used automatically. |
114 | | //! types { |
115 | | //! Error, ErrorKind, ResultExt, Result; |
116 | | //! } |
117 | | //! |
118 | | //! // Without the `Result` wrapper: |
119 | | //! // |
120 | | //! // types { |
121 | | //! // Error, ErrorKind, ResultExt; |
122 | | //! // } |
123 | | //! |
124 | | //! // Automatic conversions between this error chain and other |
125 | | //! // error chains. In this case, it will e.g. generate an |
126 | | //! // `ErrorKind` variant called `Another` which in turn contains |
127 | | //! // the `other_error::ErrorKind`, with conversions from |
128 | | //! // `other_error::Error`. |
129 | | //! // |
130 | | //! // Optionally, some attributes can be added to a variant. |
131 | | //! // |
132 | | //! // This section can be empty. |
133 | | //! links { |
134 | | //! Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)]; |
135 | | //! } |
136 | | //! |
137 | | //! // Automatic conversions between this error chain and other |
138 | | //! // error types not defined by the `error_chain!`. These will be |
139 | | //! // wrapped in a new error with, in the first case, the |
140 | | //! // `ErrorKind::Fmt` variant. The description and cause will |
141 | | //! // forward to the description and cause of the original error. |
142 | | //! // |
143 | | //! // Optionally, some attributes can be added to a variant. |
144 | | //! // |
145 | | //! // This section can be empty. |
146 | | //! foreign_links { |
147 | | //! Fmt(::std::fmt::Error); |
148 | | //! Io(::std::io::Error) #[cfg(unix)]; |
149 | | //! } |
150 | | //! |
151 | | //! // Define additional `ErrorKind` variants. Define custom responses with the |
152 | | //! // `description` and `display` calls. |
153 | | //! errors { |
154 | | //! InvalidToolchainName(t: String) { |
155 | | //! description("invalid toolchain name") |
156 | | //! display("invalid toolchain name: '{}'", t) |
157 | | //! } |
158 | | //! |
159 | | //! // You can also add commas after description/display. |
160 | | //! // This may work better with some editor auto-indentation modes: |
161 | | //! UnknownToolchainVersion(v: String) { |
162 | | //! description("unknown toolchain version"), // note the , |
163 | | //! display("unknown toolchain version: '{}'", v), // trailing comma is allowed |
164 | | //! } |
165 | | //! } |
166 | | //! |
167 | | //! // If this annotation is left off, a variant `Msg(s: String)` will be added, and `From` |
168 | | //! // impls will be provided for `String` and `&str` |
169 | | //! skip_msg_variant |
170 | | //! } |
171 | | //! |
172 | | //! # fn main() {} |
173 | | //! ``` |
174 | | //! |
175 | | //! Each section, `types`, `links`, `foreign_links`, and `errors` may |
176 | | //! be omitted if it is empty. |
177 | | //! |
178 | | //! This populates the module with a number of definitions, |
179 | | //! the most important of which are the [`Error`] type |
180 | | //! and the [`ErrorKind`] type. An example of generated code can be found in the |
181 | | //! [example_generated](example_generated/index.html) module. |
182 | | //! |
183 | | //! ## Returning new errors |
184 | | //! |
185 | | //! Introducing new error chains, with a string message: |
186 | | //! |
187 | | //! ``` |
188 | | //! # #[macro_use] extern crate error_chain; |
189 | | //! # fn main() {} |
190 | | //! # error_chain! {} |
191 | | //! fn foo() -> Result<()> { |
192 | | //! Err("foo error!".into()) |
193 | | //! } |
194 | | //! ``` |
195 | | //! |
196 | | //! Introducing new error chains, with an [`ErrorKind`]: |
197 | | //! |
198 | | //! ``` |
199 | | //! # #[macro_use] extern crate error_chain; |
200 | | //! # fn main() {} |
201 | | //! error_chain! { |
202 | | //! errors { FooError } |
203 | | //! } |
204 | | //! |
205 | | //! fn foo() -> Result<()> { |
206 | | //! Err(ErrorKind::FooError.into()) |
207 | | //! } |
208 | | //! ``` |
209 | | //! |
210 | | //! Note that the return type is the typedef [`Result`], which is |
211 | | //! defined by the macro as `pub type Result<T> = |
212 | | //! ::std::result::Result<T, Error>`. Note that in both cases |
213 | | //! [`.into()`] is called to convert a type into the [`Error`] type; both |
214 | | //! strings and [`ErrorKind`] have [`From`] conversions to turn them into |
215 | | //! [`Error`]. |
216 | | //! |
217 | | //! When the error is emitted behind the `?` operator, the explicit conversion |
218 | | //! isn't needed; `Err(ErrorKind)` will automatically be converted to `Err(Error)`. |
219 | | //! So the below is equivalent to the previous: |
220 | | //! |
221 | | //! ``` |
222 | | //! # #[macro_use] extern crate error_chain; |
223 | | //! # fn main() {} |
224 | | //! # error_chain! { errors { FooError } } |
225 | | //! fn foo() -> Result<()> { |
226 | | //! Ok(Err(ErrorKind::FooError)?) |
227 | | //! } |
228 | | //! |
229 | | //! fn bar() -> Result<()> { |
230 | | //! Ok(Err("bogus!")?) |
231 | | //! } |
232 | | //! ``` |
233 | | //! |
234 | | //! ## The `bail!` macro |
235 | | //! |
236 | | //! The above method of introducing new errors works but is a little |
237 | | //! verbose. Instead, we can use the [`bail!`] macro, which performs an early return |
238 | | //! with conversions done automatically. |
239 | | //! |
240 | | //! With [`bail!`] the previous examples look like: |
241 | | //! |
242 | | //! ``` |
243 | | //! # #[macro_use] extern crate error_chain; |
244 | | //! # fn main() {} |
245 | | //! # error_chain! { errors { FooError } } |
246 | | //! fn foo() -> Result<()> { |
247 | | //! if true { |
248 | | //! bail!(ErrorKind::FooError); |
249 | | //! } else { |
250 | | //! Ok(()) |
251 | | //! } |
252 | | //! } |
253 | | //! |
254 | | //! fn bar() -> Result<()> { |
255 | | //! if true { |
256 | | //! bail!("bogus!"); |
257 | | //! } else { |
258 | | //! Ok(()) |
259 | | //! } |
260 | | //! } |
261 | | //! ``` |
262 | | //! |
263 | | //! ## Chaining errors |
264 | | //! error-chain supports extending an error chain by appending new errors. |
265 | | //! This can be done on a Result or on an existing Error. |
266 | | //! |
267 | | //! To extend the error chain: |
268 | | //! |
269 | | //! ``` |
270 | | //! # #[macro_use] extern crate error_chain; |
271 | | //! # fn main() {} |
272 | | //! # error_chain! {} |
273 | | //! # fn do_something() -> Result<()> { unimplemented!() } |
274 | | //! # fn test() -> Result<()> { |
275 | | //! let res: Result<()> = do_something().chain_err(|| "something went wrong"); |
276 | | //! # Ok(()) |
277 | | //! # } |
278 | | //! ``` |
279 | | //! |
280 | | //! [`chain_err`] can be called on any [`Result`] type where the contained |
281 | | //! error type implements [`std::error::Error`]` + `[`Send`]` + 'static`, as long as |
282 | | //! the [`Result`] type's corresponding [`ResultExt`] trait is in scope. If |
283 | | //! the [`Result`] is an `Err` then [`chain_err`] evaluates the closure, |
284 | | //! which returns *some type that can be converted to [`ErrorKind`]*, |
285 | | //! boxes the original error to store as the cause, then returns a new |
286 | | //! error containing the original error. |
287 | | //! |
288 | | //! Calling [`chain_err`][Error_chain_err] on an existing [`Error`] instance has |
289 | | //! the same signature and produces the same outcome as being called on a |
290 | | //! [`Result`] matching the properties described above. This is most useful when |
291 | | //! partially handling errors using the [`map_err`] function. |
292 | | //! |
293 | | //! To chain an error directly, use [`with_chain`]: |
294 | | //! |
295 | | //! ``` |
296 | | //! # #[macro_use] extern crate error_chain; |
297 | | //! # fn main() {} |
298 | | //! # error_chain! {} |
299 | | //! # fn do_something() -> Result<()> { unimplemented!() } |
300 | | //! # fn test() -> Result<()> { |
301 | | //! let res: Result<()> = |
302 | | //! do_something().map_err(|e| Error::with_chain(e, "something went wrong")); |
303 | | //! # Ok(()) |
304 | | //! # } |
305 | | //! ``` |
306 | | //! |
307 | | //! ## Linking errors |
308 | | //! |
309 | | //! To convert an error from another error chain to this error chain: |
310 | | //! |
311 | | //! ``` |
312 | | //! # #[macro_use] extern crate error_chain; |
313 | | //! # fn main() {} |
314 | | //! # mod other { error_chain! {} } |
315 | | //! error_chain! { |
316 | | //! links { |
317 | | //! OtherError(other::Error, other::ErrorKind); |
318 | | //! } |
319 | | //! } |
320 | | //! |
321 | | //! fn do_other_thing() -> other::Result<()> { unimplemented!() } |
322 | | //! |
323 | | //! # fn test() -> Result<()> { |
324 | | //! let res: Result<()> = do_other_thing().map_err(|e| e.into()); |
325 | | //! # Ok(()) |
326 | | //! # } |
327 | | //! ``` |
328 | | //! |
329 | | //! The [`Error`] and [`ErrorKind`] types implements [`From`] for the corresponding |
330 | | //! types of all linked error chains. Linked errors do not introduce a new |
331 | | //! cause to the error chain. |
332 | | //! |
333 | | //! ## Matching errors |
334 | | //! |
335 | | //! error-chain error variants are matched with simple patterns. |
336 | | //! [`Error`] is a tuple struct and its first field is the [`ErrorKind`], |
337 | | //! making dispatching on error kinds relatively compact: |
338 | | //! |
339 | | //! ``` |
340 | | //! # #[macro_use] extern crate error_chain; |
341 | | //! # fn main() { |
342 | | //! error_chain! { |
343 | | //! errors { |
344 | | //! InvalidToolchainName(t: String) { |
345 | | //! description("invalid toolchain name") |
346 | | //! display("invalid toolchain name: '{}'", t) |
347 | | //! } |
348 | | //! } |
349 | | //! } |
350 | | //! |
351 | | //! match Error::from("error!") { |
352 | | //! Error(ErrorKind::InvalidToolchainName(_), _) => { } |
353 | | //! Error(ErrorKind::Msg(_), _) => { } |
354 | | //! _ => { } |
355 | | //! } |
356 | | //! # } |
357 | | //! ``` |
358 | | //! |
359 | | //! Chained errors are also matched with (relatively) compact syntax |
360 | | //! |
361 | | //! ``` |
362 | | //! # #[macro_use] extern crate error_chain; |
363 | | //! mod utils { |
364 | | //! error_chain! { |
365 | | //! errors { |
366 | | //! BadStuff { |
367 | | //! description("bad stuff") |
368 | | //! } |
369 | | //! } |
370 | | //! } |
371 | | //! } |
372 | | //! |
373 | | //! mod app { |
374 | | //! error_chain! { |
375 | | //! links { |
376 | | //! Utils(::utils::Error, ::utils::ErrorKind); |
377 | | //! } |
378 | | //! } |
379 | | //! } |
380 | | //! |
381 | | //! |
382 | | //! # fn main() { |
383 | | //! match app::Error::from("error!") { |
384 | | //! app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { } |
385 | | //! _ => { } |
386 | | //! } |
387 | | //! # } |
388 | | //! ``` |
389 | | //! |
390 | | //! ## Inspecting errors |
391 | | //! |
392 | | //! An error-chain error contains information about the error itself, a backtrace, and the chain |
393 | | //! of causing errors. For reporting purposes, this information can be accessed as follows. |
394 | | //! |
395 | | //! ``` |
396 | | //! # #[macro_use] extern crate error_chain; |
397 | | //! use error_chain::ChainedError; // for e.display_chain() |
398 | | //! |
399 | | //! error_chain! { |
400 | | //! errors { |
401 | | //! InvalidToolchainName(t: String) { |
402 | | //! description("invalid toolchain name") |
403 | | //! display("invalid toolchain name: '{}'", t) |
404 | | //! } |
405 | | //! } |
406 | | //! } |
407 | | //! |
408 | | //! # fn main() { |
409 | | //! // Generate an example error to inspect: |
410 | | //! let e = "xyzzy".parse::<i32>() |
411 | | //! .chain_err(|| ErrorKind::InvalidToolchainName("xyzzy".to_string())) |
412 | | //! .unwrap_err(); |
413 | | //! |
414 | | //! // Get the brief description of the error: |
415 | | //! assert_eq!(e.description(), "invalid toolchain name"); |
416 | | //! |
417 | | //! // Get the display version of the error: |
418 | | //! assert_eq!(e.to_string(), "invalid toolchain name: 'xyzzy'"); |
419 | | //! |
420 | | //! // Get the full cause and backtrace: |
421 | | //! println!("{}", e.display_chain().to_string()); |
422 | | //! // Error: invalid toolchain name: 'xyzzy' |
423 | | //! // Caused by: invalid digit found in string |
424 | | //! // stack backtrace: |
425 | | //! // 0: 0x7fa9f684fc94 - backtrace::backtrace::libunwind::trace |
426 | | //! // at src/backtrace/libunwind.rs:53 |
427 | | //! // - backtrace::backtrace::trace<closure> |
428 | | //! // at src/backtrace/mod.rs:42 |
429 | | //! // 1: 0x7fa9f6850b0e - backtrace::capture::{{impl}}::new |
430 | | //! // at out/capture.rs:79 |
431 | | //! // [..] |
432 | | //! # } |
433 | | //! ``` |
434 | | //! |
435 | | //! The [`Error`] and [`ErrorKind`] types also allow programmatic access to these elements. |
436 | | //! |
437 | | //! ## Foreign links |
438 | | //! |
439 | | //! Errors that do not conform to the same conventions as this library |
440 | | //! can still be included in the error chain. They are considered "foreign |
441 | | //! errors", and are declared using the `foreign_links` block of the |
442 | | //! [`error_chain!`] macro. [`Error`]s are automatically created from |
443 | | //! foreign errors by the `?` operator. |
444 | | //! |
445 | | //! Foreign links and regular links have one crucial difference: |
446 | | //! [`From`] conversions for regular links *do not introduce a new error |
447 | | //! into the error chain*, while conversions for foreign links *always |
448 | | //! introduce a new error into the error chain*. So for the example |
449 | | //! above all errors deriving from the [`std::fmt::Error`] type will be |
450 | | //! presented to the user as a new [`ErrorKind`] variant, and the |
451 | | //! cause will be the original [`std::fmt::Error`] error. In contrast, when |
452 | | //! `other_error::Error` is converted to `Error` the two `ErrorKind`s |
453 | | //! are converted between each other to create a new `Error` but the |
454 | | //! old error is discarded; there is no "cause" created from the |
455 | | //! original error. |
456 | | //! |
457 | | //! ## Backtraces |
458 | | //! |
459 | | //! If the `RUST_BACKTRACE` environment variable is set to anything |
460 | | //! but ``0``, the earliest non-foreign error to be generated creates |
461 | | //! a single backtrace, which is passed through all [`From`] conversions |
462 | | //! and [`chain_err`] invocations of compatible types. To read the |
463 | | //! backtrace just call the [`backtrace`] method. |
464 | | //! |
465 | | //! Backtrace generation can be disabled by turning off the `backtrace` feature. |
466 | | //! |
467 | | //! The Backtrace contains a Vec of [`BacktraceFrame`]s that can be operated |
468 | | //! on directly. For example, to only see the files and line numbers of code |
469 | | //! within your own project. |
470 | | //! |
471 | | //! ``` |
472 | | //! # #[macro_use] |
473 | | //! # extern crate error_chain; |
474 | | //! # mod errors { |
475 | | //! # error_chain! { |
476 | | //! # foreign_links { |
477 | | //! # Io(::std::io::Error); |
478 | | //! # } |
479 | | //! # } |
480 | | //! # } |
481 | | //! # use errors::*; |
482 | | //! # #[cfg(feature="backtrace")] |
483 | | //! # fn main() { |
484 | | //! if let Err(ref e) = open_file() { |
485 | | //! if let Some(backtrace) = e.backtrace() { |
486 | | //! let frames = backtrace.frames(); |
487 | | //! for frame in frames.iter() { |
488 | | //! for symbol in frame.symbols().iter() { |
489 | | //! if let (Some(file), Some(lineno)) = (symbol.filename(), symbol.lineno()) { |
490 | | //! if file.display().to_string()[0..3] == "src".to_string(){ |
491 | | //! println!("{}:{}", file.display().to_string(), lineno); |
492 | | //! } |
493 | | //! } |
494 | | //! } |
495 | | //! } |
496 | | //! } |
497 | | //! }; |
498 | | //! # } |
499 | | //! # #[cfg(not(feature="backtrace"))] |
500 | | //! # fn main() { } |
501 | | //! |
502 | | //! fn open_file() -> Result<()> { |
503 | | //! std::fs::File::open("does_not_exist")?; |
504 | | //! Ok(()) |
505 | | //! } |
506 | | //! ``` |
507 | | //! |
508 | | //! ## Iteration |
509 | | //! |
510 | | //! The [`iter`] method returns an iterator over the chain of error boxes. |
511 | | //! |
512 | | //! [error-type]: https://github.com/DanielKeep/rust-error-type |
513 | | //! [quick-error]: https://github.com/tailhook/quick-error |
514 | | |
515 | | //! [`display_chain`]: trait.ChainedError.html#method.display_chain |
516 | | //! [`error_chain!`]: macro.error_chain.html |
517 | | //! [`bail!`]: macro.bail.html |
518 | | //! [`Backtrace`]: struct.Backtrace.html |
519 | | |
520 | | //! [`Error`]: example_generated/struct.Error.html |
521 | | //! [`with_chain`]: example_generated/struct.Error.html#method.with_chain |
522 | | //! [Error_chain_err]: example_generated/struct.Error.html#method.chain_err |
523 | | //! [`cause`]: example_generated/struct.Error.html#method.cause |
524 | | //! [`backtrace`]: example_generated/struct.Error.html#method.backtrace |
525 | | //! [`iter`]: example_generated/struct.Error.html#method.iter |
526 | | //! [`ErrorKind`]: example_generated/enum.ErrorKind.html |
527 | | //! [`description`]: example_generated/enum.ErrorKind.html#method.description |
528 | | //! [`Result`]: example_generated/type.Result.html |
529 | | //! [`ResultExt`]: example_generated/trait.ResultExt.html |
530 | | //! [`chain_err`]: example_generated/trait.ResultExt.html#tymethod.chain_err |
531 | | |
532 | | //! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html |
533 | | //! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html |
534 | | //! [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html |
535 | | //! [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html |
536 | | //! [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html |
537 | | //! [`std::fmt::Error`]: https://doc.rust-lang.org/std/fmt/struct.Error.html |
538 | | //! [`.into()`]: https://doc.rust-lang.org/std/convert/trait.Into.html#tymethod.into |
539 | | //! [`map_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err |
540 | | //! [`BacktraceFrame`]: https://docs.rs/backtrace/0.3.2/backtrace/struct.BacktraceFrame.html |
541 | | |
542 | | use std::error; |
543 | | use std::fmt; |
544 | | use std::iter::Iterator; |
545 | | |
546 | | #[macro_use] |
547 | | mod impl_error_chain_kind; |
548 | | #[macro_use] |
549 | | mod error_chain; |
550 | | #[macro_use] |
551 | | mod quick_main; |
552 | | pub use quick_main::ExitCode; |
553 | | mod backtrace; |
554 | | #[cfg(feature = "example_generated")] |
555 | | pub mod example_generated; |
556 | | pub use backtrace::Backtrace; |
557 | | #[doc(hidden)] |
558 | | pub use backtrace::InternalBacktrace; |
559 | | |
560 | | #[derive(Debug)] |
561 | | #[allow(unknown_lints, bare_trait_objects)] |
562 | | /// Iterator over the error chain using the `Error::cause()` method. |
563 | | pub struct Iter<'a>(Option<&'a error::Error>); |
564 | | |
565 | | impl<'a> Iter<'a> { |
566 | | /// Returns a new iterator over the error chain using `Error::cause()`. |
567 | | #[allow(unknown_lints, bare_trait_objects)] |
568 | 0 | pub fn new(err: Option<&'a error::Error>) -> Iter<'a> { |
569 | 0 | Iter(err) |
570 | 0 | } |
571 | | } |
572 | | |
573 | | #[allow(unknown_lints, bare_trait_objects)] |
574 | | impl<'a> Iterator for Iter<'a> { |
575 | | type Item = &'a error::Error; |
576 | | |
577 | 0 | fn next<'b>(&'b mut self) -> Option<&'a error::Error> { |
578 | 0 | match self.0.take() { |
579 | 0 | Some(e) => { |
580 | 0 | self.0 = match () { |
581 | 0 | #[cfg(not(has_error_source))] |
582 | 0 | () => e.cause(), |
583 | 0 | #[cfg(has_error_source)] |
584 | 0 | () => e.source(), |
585 | 0 | }; |
586 | 0 | Some(e) |
587 | | } |
588 | 0 | None => None, |
589 | | } |
590 | 0 | } |
591 | | } |
592 | | |
593 | | /// This trait is implemented on all the errors generated by the `error_chain` |
594 | | /// macro. |
595 | | pub trait ChainedError: error::Error + Send + 'static { |
596 | | /// Associated kind type. |
597 | | type ErrorKind; |
598 | | |
599 | | /// Constructs an error from a kind, and generates a backtrace. |
600 | | fn from_kind(kind: Self::ErrorKind) -> Self |
601 | | where |
602 | | Self: Sized; |
603 | | |
604 | | /// Constructs a chained error from another error and a kind, and generates a backtrace. |
605 | | fn with_chain<E, K>(error: E, kind: K) -> Self |
606 | | where |
607 | | Self: Sized, |
608 | | E: ::std::error::Error + Send + 'static, |
609 | | K: Into<Self::ErrorKind>; |
610 | | |
611 | | /// Returns the kind of the error. |
612 | | fn kind(&self) -> &Self::ErrorKind; |
613 | | |
614 | | /// Iterates over the error chain. |
615 | | fn iter(&self) -> Iter; |
616 | | |
617 | | /// Returns the backtrace associated with this error. |
618 | | fn backtrace(&self) -> Option<&Backtrace>; |
619 | | |
620 | | /// Returns an object which implements `Display` for printing the full |
621 | | /// context of this error. |
622 | | /// |
623 | | /// The full cause chain and backtrace, if present, will be printed. |
624 | 0 | fn display_chain<'a>(&'a self) -> DisplayChain<'a, Self> { |
625 | 0 | DisplayChain(self) |
626 | 0 | } |
627 | | |
628 | | /// Extends the error chain with a new entry. |
629 | | fn chain_err<F, EK>(self, error: F) -> Self |
630 | | where |
631 | | F: FnOnce() -> EK, |
632 | | EK: Into<Self::ErrorKind>; |
633 | | |
634 | | /// Creates an error from its parts. |
635 | | #[doc(hidden)] |
636 | | fn new(kind: Self::ErrorKind, state: State) -> Self |
637 | | where |
638 | | Self: Sized; |
639 | | |
640 | | /// Returns the first known backtrace, either from its State or from one |
641 | | /// of the errors from `foreign_links`. |
642 | | #[doc(hidden)] |
643 | | #[allow(unknown_lints, bare_trait_objects)] |
644 | | fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<InternalBacktrace> |
645 | | where |
646 | | Self: Sized; |
647 | | } |
648 | | |
649 | | /// A struct which formats an error for output. |
650 | | #[derive(Debug)] |
651 | | pub struct DisplayChain<'a, T: 'a + ?Sized>(&'a T); |
652 | | |
653 | | impl<'a, T> fmt::Display for DisplayChain<'a, T> |
654 | | where |
655 | | T: ChainedError, |
656 | | { |
657 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
658 | 0 | writeln!(fmt, "Error: {}", self.0)?; |
659 | | |
660 | 0 | for e in self.0.iter().skip(1) { |
661 | 0 | writeln!(fmt, "Caused by: {}", e)?; |
662 | | } |
663 | | |
664 | 0 | if let Some(backtrace) = ChainedError::backtrace(self.0) { |
665 | 0 | writeln!(fmt, "{:?}", backtrace)?; |
666 | 0 | } |
667 | | |
668 | 0 | Ok(()) |
669 | 0 | } |
670 | | } |
671 | | |
672 | | /// Common state between errors. |
673 | | #[derive(Debug)] |
674 | | #[doc(hidden)] |
675 | | #[allow(unknown_lints, bare_trait_objects)] |
676 | | pub struct State { |
677 | | /// Next error in the error chain. |
678 | | pub next_error: Option<Box<error::Error + Send>>, |
679 | | /// Backtrace for the current error. |
680 | | pub backtrace: InternalBacktrace, |
681 | | } |
682 | | |
683 | | impl Default for State { |
684 | 0 | fn default() -> State { |
685 | 0 | State { |
686 | 0 | next_error: None, |
687 | 0 | backtrace: InternalBacktrace::new(), |
688 | 0 | } |
689 | 0 | } |
690 | | } |
691 | | |
692 | | impl State { |
693 | | /// Creates a new State type |
694 | | #[allow(unknown_lints, bare_trait_objects)] |
695 | 0 | pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State { |
696 | 0 | let backtrace = CE::extract_backtrace(&*e).unwrap_or_else(InternalBacktrace::new); |
697 | 0 | State { |
698 | 0 | next_error: Some(e), |
699 | 0 | backtrace: backtrace, |
700 | 0 | } |
701 | 0 | } Unexecuted instantiation: <error_chain::State>::new::<syslog::errors::Error> Unexecuted instantiation: <error_chain::State>::new::<_> Unexecuted instantiation: <error_chain::State>::new::<syslog::errors::Error> |
702 | | |
703 | | /// Returns the inner backtrace if present. |
704 | 0 | pub fn backtrace(&self) -> Option<&Backtrace> { |
705 | 0 | self.backtrace.as_backtrace() |
706 | 0 | } |
707 | | } |
708 | | |
709 | | /// Exits a function early with an error |
710 | | /// |
711 | | /// The `bail!` macro provides an easy way to exit a function. |
712 | | /// `bail!(expr)` is equivalent to writing. |
713 | | /// |
714 | | /// ``` |
715 | | /// # #[macro_use] extern crate error_chain; |
716 | | /// # error_chain! { } |
717 | | /// # fn main() { } |
718 | | /// # fn foo() -> Result<()> { |
719 | | /// # let expr = ""; |
720 | | /// return Err(expr.into()); |
721 | | /// # } |
722 | | /// ``` |
723 | | /// |
724 | | /// And as shorthand it takes a formatting string a la `println!`: |
725 | | /// |
726 | | /// ``` |
727 | | /// # #[macro_use] extern crate error_chain; |
728 | | /// # error_chain! { } |
729 | | /// # fn main() { } |
730 | | /// # fn foo() -> Result<()> { |
731 | | /// # let n = 0; |
732 | | /// bail!("bad number: {}", n); |
733 | | /// # } |
734 | | /// ``` |
735 | | /// |
736 | | /// # Examples |
737 | | /// |
738 | | /// Bailing on a custom error: |
739 | | /// |
740 | | /// ``` |
741 | | /// # #[macro_use] extern crate error_chain; |
742 | | /// # fn main() {} |
743 | | /// error_chain! { |
744 | | /// errors { FooError } |
745 | | /// } |
746 | | /// |
747 | | /// fn foo() -> Result<()> { |
748 | | /// if bad_condition() { |
749 | | /// bail!(ErrorKind::FooError); |
750 | | /// } |
751 | | /// |
752 | | /// Ok(()) |
753 | | /// } |
754 | | /// |
755 | | /// # fn bad_condition() -> bool { true } |
756 | | /// ``` |
757 | | /// |
758 | | /// Bailing on a formatted string: |
759 | | /// |
760 | | /// ``` |
761 | | /// # #[macro_use] extern crate error_chain; |
762 | | /// # fn main() {} |
763 | | /// error_chain! { } |
764 | | /// |
765 | | /// fn foo() -> Result<()> { |
766 | | /// if let Some(bad_num) = bad_condition() { |
767 | | /// bail!("so bad: {}", bad_num); |
768 | | /// } |
769 | | /// |
770 | | /// Ok(()) |
771 | | /// } |
772 | | /// |
773 | | /// # fn bad_condition() -> Option<i8> { None } |
774 | | /// ``` |
775 | | #[macro_export] |
776 | | macro_rules! bail { |
777 | | ($e:expr) => { |
778 | | return Err($e.into()); |
779 | | }; |
780 | | ($fmt:expr, $($arg:tt)+) => { |
781 | | return Err(format!($fmt, $($arg)+).into()); |
782 | | }; |
783 | | } |
784 | | |
785 | | /// Exits a function early with an error if the condition is not satisfied |
786 | | /// |
787 | | /// The `ensure!` macro is a convenience helper that provides a way to exit |
788 | | /// a function with an error if the given condition fails. |
789 | | /// |
790 | | /// As an example, `ensure!(condition, "error code: {}", errcode)` is equivalent to |
791 | | /// |
792 | | /// ``` |
793 | | /// # #[macro_use] extern crate error_chain; |
794 | | /// # error_chain! { } |
795 | | /// # fn main() { } |
796 | | /// # fn foo() -> Result<()> { |
797 | | /// # let errcode = 0u8; |
798 | | /// # let condition = true; |
799 | | /// if !condition { |
800 | | /// bail!("error code: {}", errcode); |
801 | | /// } |
802 | | /// # Ok(()) |
803 | | /// # } |
804 | | /// ``` |
805 | | /// |
806 | | /// See documentation for `bail!` macro for further details. |
807 | | #[macro_export(local_inner_macros)] |
808 | | macro_rules! ensure { |
809 | | ($cond:expr, $e:expr) => { |
810 | | if !($cond) { |
811 | | bail!($e); |
812 | | } |
813 | | }; |
814 | | ($cond:expr, $fmt:expr, $($arg:tt)+) => { |
815 | | if !($cond) { |
816 | | bail!($fmt, $($arg)+); |
817 | | } |
818 | | }; |
819 | | } |
820 | | |
821 | | #[doc(hidden)] |
822 | | pub mod mock { |
823 | | error_chain! {} |
824 | | } |