|
1 |
| -//! Interfaces for working with Errors. |
2 |
| -//! |
3 |
| -//! # Error Handling In Rust |
4 |
| -//! |
5 |
| -//! The Rust language provides two complementary systems for constructing / |
6 |
| -//! representing, reporting, propagating, reacting to, and discarding errors. |
7 |
| -//! These responsibilities are collectively known as "error handling." The |
8 |
| -//! components of the first system, the panic runtime and interfaces, are most |
9 |
| -//! commonly used to represent bugs that have been detected in your program. The |
10 |
| -//! components of the second system, `Result`, the error traits, and user |
11 |
| -//! defined types, are used to represent anticipated runtime failure modes of |
12 |
| -//! your program. |
13 |
| -//! |
14 |
| -//! ## The Panic Interfaces |
15 |
| -//! |
16 |
| -//! The following are the primary interfaces of the panic system and the |
17 |
| -//! responsibilities they cover: |
18 |
| -//! |
19 |
| -//! * [`panic!`] and [`panic_any`] (Constructing, Propagated automatically) |
20 |
| -//! * [`PanicInfo`] (Reporting) |
21 |
| -//! * [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting) |
22 |
| -//! * [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating) |
23 |
| -//! |
24 |
| -//! The following are the primary interfaces of the error system and the |
25 |
| -//! responsibilities they cover: |
26 |
| -//! |
27 |
| -//! * [`Result`] (Propagating, Reacting) |
28 |
| -//! * The [`Error`] trait (Reporting) |
29 |
| -//! * User defined types (Constructing / Representing) |
30 |
| -//! * [`match`] and [`downcast`] (Reacting) |
31 |
| -//! * The question mark operator ([`?`]) (Propagating) |
32 |
| -//! * The partially stable [`Try`] traits (Propagating, Constructing) |
33 |
| -//! * [`Termination`] (Reporting) |
34 |
| -//! |
35 |
| -//! ## Converting Errors into Panics |
36 |
| -//! |
37 |
| -//! The panic and error systems are not entirely distinct. Often times errors |
38 |
| -//! that are anticipated runtime failures in an API might instead represent bugs |
39 |
| -//! to a caller. For these situations the standard library provides APIs for |
40 |
| -//! constructing panics with an `Error` as it's source. |
41 |
| -//! |
42 |
| -//! * [`Result::unwrap`] |
43 |
| -//! * [`Result::expect`] |
44 |
| -//! |
45 |
| -//! These functions are equivalent, they either return the inner value if the |
46 |
| -//! `Result` is `Ok` or panic if the `Result` is `Err` printing the inner error |
47 |
| -//! as the source. The only difference between them is that with `expect` you |
48 |
| -//! provide a panic error message to be printed alongside the source, whereas |
49 |
| -//! `unwrap` has a default message indicating only that you unwraped an `Err`. |
50 |
| -//! |
51 |
| -//! Of the two, `expect` is generally preferred since its `msg` field allows you |
52 |
| -//! to convey your intent and assumptions which makes tracking down the source |
53 |
| -//! of a panic easier. `unwrap` on the other hand can still be a good fit in |
54 |
| -//! situations where you can trivially show that a piece of code will never |
55 |
| -//! panic, such as `"127.0.0.1".parse::<std::net::IpAddr>().unwrap()` or early |
56 |
| -//! prototyping. |
57 |
| -//! |
58 |
| -//! # Common Message Styles |
59 |
| -//! |
60 |
| -//! There are two common styles for how people word `expect` messages. Using |
61 |
| -//! the message to present information to users encountering a panic |
62 |
| -//! ("expect as error message") or using the message to present information |
63 |
| -//! to developers debugging the panic ("expect as precondition"). |
64 |
| -//! |
65 |
| -//! In the former case the expect message is used to describe the error that |
66 |
| -//! has occurred which is considered a bug. Consider the following example: |
67 |
| -//! |
68 |
| -//! ```should_panic |
69 |
| -//! // Read environment variable, panic if it is not present |
70 |
| -//! let path = std::env::var("IMPORTANT_PATH").unwrap(); |
71 |
| -//! ``` |
72 |
| -//! |
73 |
| -//! In the "expect as error message" style we would use expect to describe |
74 |
| -//! that the environment variable was not set when it should have been: |
75 |
| -//! |
76 |
| -//! ```should_panic |
77 |
| -//! let path = std::env::var("IMPORTANT_PATH") |
78 |
| -//! .expect("env variable `IMPORTANT_PATH` is not set"); |
79 |
| -//! ``` |
80 |
| -//! |
81 |
| -//! In the "expect as precondition" style, we would instead describe the |
82 |
| -//! reason we _expect_ the `Result` should be `Ok`. With this style we would |
83 |
| -//! prefer to write: |
84 |
| -//! |
85 |
| -//! ```should_panic |
86 |
| -//! let path = std::env::var("IMPORTANT_PATH") |
87 |
| -//! .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); |
88 |
| -//! ``` |
89 |
| -//! |
90 |
| -//! The "expect as error message" style does not work as well with the |
91 |
| -//! default output of the std panic hooks, and often ends up repeating |
92 |
| -//! information that is already communicated by the source error being |
93 |
| -//! unwrapped: |
94 |
| -//! |
95 |
| -//! ```text |
96 |
| -//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` is not set: NotPresent', src/main.rs:4:6 |
97 |
| -//! ``` |
98 |
| -//! |
99 |
| -//! In this example we end up mentioning that an env variable is not set, |
100 |
| -//! followed by our source message that says the env is not present, the |
101 |
| -//! only additional information we're communicating is the name of the |
102 |
| -//! environment variable being checked. |
103 |
| -//! |
104 |
| -//! The "expect as precondition" style instead focuses on source code |
105 |
| -//! readability, making it easier to understand what must have gone wrong in |
106 |
| -//! situations where panics are being used to represent bugs exclusively. |
107 |
| -//! Also, by framing our expect in terms of what "SHOULD" have happened to |
108 |
| -//! prevent the source error, we end up introducing new information that is |
109 |
| -//! independent from our source error. |
110 |
| -//! |
111 |
| -//! ```text |
112 |
| -//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent', src/main.rs:4:6 |
113 |
| -//! ``` |
114 |
| -//! |
115 |
| -//! In this example we are communicating not only the name of the |
116 |
| -//! environment variable that should have been set, but also an explanation |
117 |
| -//! for why it should have been set, and we let the source error display as |
118 |
| -//! a clear contradiction to our expectation. |
119 |
| -//! |
120 |
| -//! **Hint**: If you're having trouble remembering how to phrase |
121 |
| -//! expect-as-precondition style error messages remember to focus on the word |
122 |
| -//! "should" as in "env variable should be set by blah" or "the given binary |
123 |
| -//! should be available and executable by the current user". |
124 |
| -//! |
125 |
| -//! [`panic_any`]: crate::panic::panic_any |
126 |
| -//! [`PanicInfo`]: crate::panic::PanicInfo |
127 |
| -//! [`catch_unwind`]: crate::panic::catch_unwind |
128 |
| -//! [`resume_unwind`]: crate::panic::resume_unwind |
129 |
| -//! [`downcast`]: crate::error::Error |
130 |
| -//! [`Termination`]: crate::process::Termination |
131 |
| -//! [`Try`]: crate::ops::Try |
132 |
| -//! [panic hook]: crate::panic::set_hook |
133 |
| -//! [`set_hook`]: crate::panic::set_hook |
134 |
| -//! [`take_hook`]: crate::panic::take_hook |
135 |
| -//! [panic-handler]: <https://doc.rust-lang.org/nomicon/panic-handler.html> |
136 |
| -//! [`match`]: ../../std/keyword.match.html |
137 |
| -//! [`?`]: ../../std/result/index.html#the-question-mark-operator- |
138 |
| -
|
| 1 | +#![doc = include_str!("../../core/src/error.md")] |
139 | 2 | #![stable(feature = "rust1", since = "1.0.0")]
|
140 | 3 |
|
141 | 4 | // A note about crates and the facade:
|
|
0 commit comments