diff options
| -rw-r--r-- | library/core/src/result.rs | 72 | ||||
| -rw-r--r-- | library/std/src/error.rs | 133 |
2 files changed, 138 insertions, 67 deletions
diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 99d39b7011c..342acea29dc 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1024,79 +1024,19 @@ impl<T, E> Result<T, E> { /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure` /// ``` /// - /// # Common Message Styles + /// # Recommended Message Style /// - /// There are two common styles for how people word `expect` messages. Using - /// the message to present information to users encountering a panic - /// ("expect as error message") or using the message to present information - /// to developers debugging the panic ("expect as precondition"). - /// - /// In the former case the expect message is used to describe the error that - /// has occurred which is considered a bug. Consider the following example: - /// - /// ```should_panic - /// // Read environment variable, panic if it is not present - /// let path = std::env::var("IMPORTANT_PATH").unwrap(); - /// ``` - /// - /// In the "expect as error message" style we would use expect to describe - /// that the environment variable was not set when it should have been: - /// - /// ```should_panic - /// let path = std::env::var("IMPORTANT_PATH") - /// .expect("env variable `IMPORTANT_PATH` is not set"); - /// ``` - /// - /// In the "expect as precondition" style, we would instead describe the - /// reason we _expect_ the `Result` should be `Ok`. With this style we would - /// prefer to write: + /// We recommend that `expect` messages are used to describe the reason you + /// _expect_ the `Result` should be `Ok`. /// /// ```should_panic /// let path = std::env::var("IMPORTANT_PATH") /// .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); /// ``` /// - /// The "expect as error message" style does not work as well with the - /// default output of the std panic hooks, and often ends up repeating - /// information that is already communicated by the source error being - /// unwrapped: - /// - /// ```text - /// thread 'main' panicked at 'env variable `IMPORTANT_PATH` is not set: NotPresent', src/main.rs:4:6 - /// ``` - /// - /// In this example we end up mentioning that an env variable is not set, - /// followed by our source message that says the env is not present, the - /// only additional information we're communicating is the name of the - /// environment variable being checked. - /// - /// The "expect as precondition" style instead focuses on source code - /// readability, making it easier to understand what must have gone wrong in - /// situations where panics are being used to represent bugs exclusively. - /// Also, by framing our expect in terms of what "SHOULD" have happened to - /// prevent the source error, we end up introducing new information that is - /// independent from our source error. - /// - /// ```text - /// thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent', src/main.rs:4:6 - /// ``` - /// - /// In this example we are communicating not only the name of the - /// environment variable that should have been set, but also an explanation - /// for why it should have been set, and we let the source error display as - /// a clear contradiction to our expectation. - /// - /// For programs where panics may be user facing, either style works best - /// when paired with a custom [panic hook] like the one provided by the CLI - /// working group library, [`human-panic`]. This panic hook dumps the panic - /// messages to a crash report file while showing users a more friendly - /// "Oops, something went wrong!" message with a suggestion to send the - /// crash report file back to the developers. Panic messages should be used - /// to represent bugs, and the information provided back is context intended - /// for the developer, not the user. - /// - /// [panic hook]: https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html - /// [`human-panic`]: https://docs.rs/human-panic + /// For more detail on expect message styles and the reasoning behind our + /// recommendation please refer to the section on ["Common Message + /// Styles"]() in the [`std::error`]() module docs. #[inline] #[track_caller] #[stable(feature = "result_expect", since = "1.4.0")] diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 4fb94908c80..84089075f24 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -1,4 +1,135 @@ -//! Traits for working with Errors. +//! Interfaces for working with Errors. +//! +//! # Error Handling In Rust +//! +//! The Rust language provides two complementary systems for constructing / +//! representing, reporting, propagating, reacting to, and discarding errors. +//! These responsibilities are collectively known as "error handling." The +//! components of the first system, the panic runtime and interfaces, are most +//! commonly used to represent bugs that have been detected in your program. The +//! components of the second system, `Result`, the error traits, and user +//! defined types, are used to represent anticipated runtime failure modes of +//! your program. +//! +//! ## The Panic Interfaces +//! +//! The following are the primary interfaces of the panic system and the +//! responsibilities they cover: +//! +//! * [`panic!`] and [`panic_any`] (Constructing, Propagated automatically) +//! * [`PanicInfo`] (Reporting) +//! * [`set_hook`], [`take_hook`], and [`#[panic_handler]`] (Reporting) +//! * [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating) +//! +//! The following are the primary interfaces of the error system and the +//! responsibilities they cover: +//! +//! * [`Result`] (Propagating, Reacting) +//! * The [`Error`] trait (Reporting) +//! * User defined types (Constructing / Representing) +//! * `match` and [`downcast`] (Reacting) +//! * The propagation operator (`?`) (Propagating) +//! * The partially stable [`Try`] traits (Propagating, Constructing) +//! * [`Termination`] (Reporting) +//! +//! ## Converting Errors into Panics +//! +//! The panic and error systems are not entirely distinct. Often times errors +//! that are anticipated runtime failures in an API might instead represent bugs +//! to a caller. For these situations the standard library provides APIs for +//! constructing panics with an `Error` as it's source. +//! +//! * `Result::unwrap` +//! * `Result::expect` +//! +//! TODO: how do I bridge these two sections? +//! +//! * unwrap is used in prototyping +//! * expect is used in !prototyping (????) +//! +//! # Common Message Styles +//! +//! There are two common styles for how people word `expect` messages. Using +//! the message to present information to users encountering a panic +//! ("expect as error message") or using the message to present information +//! to developers debugging the panic ("expect as precondition"). +//! +//! In the former case the expect message is used to describe the error that +//! has occurred which is considered a bug. Consider the following example: +//! +//! ```should_panic +//! // Read environment variable, panic if it is not present +//! let path = std::env::var("IMPORTANT_PATH").unwrap(); +//! ``` +//! +//! In the "expect as error message" style we would use expect to describe +//! that the environment variable was not set when it should have been: +//! +//! ```should_panic +//! let path = std::env::var("IMPORTANT_PATH") +//! .expect("env variable `IMPORTANT_PATH` is not set"); +//! ``` +//! +//! In the "expect as precondition" style, we would instead describe the +//! reason we _expect_ the `Result` should be `Ok`. With this style we would +//! prefer to write: +//! +//! ```should_panic +//! let path = std::env::var("IMPORTANT_PATH") +//! .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`"); +//! ``` +//! +//! The "expect as error message" style does not work as well with the +//! default output of the std panic hooks, and often ends up repeating +//! information that is already communicated by the source error being +//! unwrapped: +//! +//! ```text +//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` is not set: NotPresent', src/main.rs:4:6 +//! ``` +//! +//! In this example we end up mentioning that an env variable is not set, +//! followed by our source message that says the env is not present, the +//! only additional information we're communicating is the name of the +//! environment variable being checked. +//! +//! The "expect as precondition" style instead focuses on source code +//! readability, making it easier to understand what must have gone wrong in +//! situations where panics are being used to represent bugs exclusively. +//! Also, by framing our expect in terms of what "SHOULD" have happened to +//! prevent the source error, we end up introducing new information that is +//! independent from our source error. +//! +//! ```text +//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent', src/main.rs:4:6 +//! ``` +//! +//! In this example we are communicating not only the name of the +//! environment variable that should have been set, but also an explanation +//! for why it should have been set, and we let the source error display as +//! a clear contradiction to our expectation. +//! +//! For programs where panics may be user facing, either style works best +//! when paired with a custom [panic hook] like the one provided by the CLI +//! working group library, [`human-panic`]. This panic hook dumps the panic +//! messages to a crash report file while showing users a more friendly +//! "Oops, something went wrong!" message with a suggestion to send the +//! crash report file back to the developers. Panic messages should be used +//! to represent bugs, and the information provided back is context intended +//! for the developer, not the user. +//! +//! [panic hook]: crate::panic::set_hook +//! [`set_hook`]: crate::panic::set_hook +//! [`take_hook`]: crate::panic::take_hook +//! [`PanicInfo`]: crate::panic::PanicInfo +//! [`panic_any`]: crate::panic::panic_any +//! [`#[panic_handler]`]: https://doc.rust-lang.org/nomicon/panic-handler.html +//! [`catch_unwind`]: crate::panic::catch_unwind +//! [`resume_unwind`]: crate::panic::resume_unwind +//! [`Termination`]: crate::process::Termination +//! [`Try`]: crate::ops::Try +//! [`downcast`]: crate::error::Error +//! [`human-panic`]: https://docs.rs/human-panic #![stable(feature = "rust1", since = "1.0.0")] |
