|
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