diff options
| author | bors <bors@rust-lang.org> | 2022-08-23 19:48:55 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-23 19:48:55 +0000 |
| commit | 060e47f74a91b28c3db28d80a6a9d6841ca51026 (patch) | |
| tree | 79655bdb6dd437f2773196bcfdda18b9f6bc2896 /library/std | |
| parent | a1bea1551b8312b6abfbbf7d49bafac2e6ce8ee4 (diff) | |
| parent | bf7611d55ee6e24647aefc4d1c82b1dba0164536 (diff) | |
Auto merge of #99917 - yaahc:error-in-core-move, r=thomcc
Move Error trait into core This PR moves the error trait from the standard library into a new unstable `error` module within the core library. The goal of this PR is to help unify error reporting across the std and no_std ecosystems, as well as open the door to integrating the error trait into the panic reporting system when reporting panics whose source is an errors (such as via `expect`). This PR is a rewrite of https://github.com/rust-lang/rust/pull/90328 using new compiler features that have been added to support error in core.
Diffstat (limited to 'library/std')
| -rw-r--r-- | library/std/src/collections/hash/map.rs | 11 | ||||
| -rw-r--r-- | library/std/src/error.rs | 307 | ||||
| -rw-r--r-- | library/std/src/io/error.rs | 9 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 3 |
4 files changed, 104 insertions, 226 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index db811343fa3..9845d1faf9a 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -9,6 +9,8 @@ use crate::borrow::Borrow; use crate::cell::Cell; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; +#[cfg(not(bootstrap))] +use crate::error::Error; use crate::fmt::{self, Debug}; #[allow(deprecated)] use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; @@ -2158,6 +2160,15 @@ impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V> { } } +#[cfg(not(bootstrap))] +#[unstable(feature = "map_try_insert", issue = "82766")] +impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> { + #[allow(deprecated)] + fn description(&self) -> &str { + "key already exists" + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> { type Item = (&'a K, &'a V); diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 4fbcfd85d7c..914f6d6d2e3 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -1,141 +1,4 @@ -//! The `Error` trait provides common functionality for 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]`][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 question mark 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`] -//! -//! These functions are equivalent, they either return the inner value if the -//! `Result` is `Ok` or panic if the `Result` is `Err` printing the inner error -//! as the source. The only difference between them is that with `expect` you -//! provide a panic error message to be printed alongside the source, whereas -//! `unwrap` has a default message indicating only that you unwraped an `Err`. -//! -//! Of the two, `expect` is generally preferred since its `msg` field allows you -//! to convey your intent and assumptions which makes tracking down the source -//! of a panic easier. `unwrap` on the other hand can still be a good fit in -//! situations where you can trivially show that a piece of code will never -//! panic, such as `"127.0.0.1".parse::<std::net::IpAddr>().unwrap()` or early -//! 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. -//! -//! **Hint**: If you're having trouble remembering how to phrase -//! expect-as-precondition style error messages remember to focus on the word -//! "should" as in "env variable should be set by blah" or "the given binary -//! should be available and executable by the current user". -//! -//! [`panic_any`]: crate::panic::panic_any -//! [`PanicInfo`]: crate::panic::PanicInfo -//! [`catch_unwind`]: crate::panic::catch_unwind -//! [`resume_unwind`]: crate::panic::resume_unwind -//! [`downcast`]: crate::error::Error -//! [`Termination`]: crate::process::Termination -//! [`Try`]: crate::ops::Try -//! [panic hook]: crate::panic::set_hook -//! [`set_hook`]: crate::panic::set_hook -//! [`take_hook`]: crate::panic::take_hook -//! [panic-handler]: <https://doc.rust-lang.org/nomicon/panic-handler.html> -//! [`match`]: ../../std/keyword.match.html -//! [`?`]: ../../std/result/index.html#the-question-mark-operator- - +#![doc = include_str!("../../core/src/error.md")] #![stable(feature = "rust1", since = "1.0.0")] // A note about crates and the facade: @@ -152,24 +15,48 @@ #[cfg(test)] mod tests; +#[cfg(bootstrap)] use core::array; +#[cfg(bootstrap)] use core::convert::Infallible; +#[cfg(bootstrap)] use crate::alloc::{AllocError, LayoutError}; -use crate::any::{Demand, Provider, TypeId}; +#[cfg(bootstrap)] +use crate::any::Demand; +#[cfg(bootstrap)] +use crate::any::{Provider, TypeId}; use crate::backtrace::Backtrace; +#[cfg(bootstrap)] use crate::borrow::Cow; +#[cfg(bootstrap)] use crate::cell; +#[cfg(bootstrap)] use crate::char; -use crate::fmt::{self, Debug, Display, Write}; +#[cfg(bootstrap)] +use crate::fmt::Debug; +#[cfg(bootstrap)] +use crate::fmt::Display; +use crate::fmt::{self, Write}; +#[cfg(bootstrap)] use crate::io; +#[cfg(bootstrap)] use crate::mem::transmute; +#[cfg(bootstrap)] use crate::num; +#[cfg(bootstrap)] use crate::str; +#[cfg(bootstrap)] use crate::string; +#[cfg(bootstrap)] use crate::sync::Arc; +#[cfg(bootstrap)] use crate::time; +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::error::Error; + /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result<T, E>`]. /// @@ -190,6 +77,7 @@ use crate::time; /// implementation for debugging via `source` chains. #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Error")] +#[cfg(bootstrap)] pub trait Error: Debug + Display { /// The lower-level source of this error, if any. /// @@ -355,6 +243,7 @@ pub trait Error: Debug + Display { fn provide<'a>(&'a self, req: &mut Demand<'a>) {} } +#[cfg(bootstrap)] #[unstable(feature = "error_generic_member_access", issue = "99301")] impl<'b> Provider for dyn Error + 'b { fn provide<'a>(&'a self, req: &mut Demand<'a>) { @@ -370,6 +259,7 @@ mod private { pub struct Internal; } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> { /// Converts a type of [`Error`] into a box of dyn [`Error`]. @@ -402,6 +292,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> { /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of @@ -440,6 +331,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl From<String> for Box<dyn Error + Send + Sync> { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. @@ -483,6 +375,7 @@ impl From<String> for Box<dyn Error + Send + Sync> { } } +#[cfg(bootstrap)] #[stable(feature = "string_box_error", since = "1.6.0")] impl From<String> for Box<dyn Error> { /// Converts a [`String`] into a box of dyn [`Error`]. @@ -504,6 +397,7 @@ impl From<String> for Box<dyn Error> { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. @@ -527,6 +421,7 @@ impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> { } } +#[cfg(bootstrap)] #[stable(feature = "string_box_error", since = "1.6.0")] impl From<&str> for Box<dyn Error> { /// Converts a [`str`] into a box of dyn [`Error`]. @@ -548,6 +443,7 @@ impl From<&str> for Box<dyn Error> { } } +#[cfg(bootstrap)] #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. @@ -569,6 +465,7 @@ impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> { } } +#[cfg(bootstrap)] #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a> From<Cow<'a, str>> for Box<dyn Error> { /// Converts a [`Cow`] into a box of dyn [`Error`]. @@ -589,9 +486,11 @@ impl<'a> From<Cow<'a, str>> for Box<dyn Error> { } } +#[cfg(bootstrap)] #[unstable(feature = "never_type", issue = "35121")] impl Error for ! {} +#[cfg(bootstrap)] #[unstable( feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", @@ -599,9 +498,11 @@ impl Error for ! {} )] impl Error for AllocError {} +#[cfg(bootstrap)] #[stable(feature = "alloc_layout", since = "1.28.0")] impl Error for LayoutError {} +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for str::ParseBoolError { #[allow(deprecated)] @@ -610,6 +511,7 @@ impl Error for str::ParseBoolError { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for str::Utf8Error { #[allow(deprecated)] @@ -618,6 +520,7 @@ impl Error for str::Utf8Error { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for num::ParseIntError { #[allow(deprecated)] @@ -626,6 +529,7 @@ impl Error for num::ParseIntError { } } +#[cfg(bootstrap)] #[stable(feature = "try_from", since = "1.34.0")] impl Error for num::TryFromIntError { #[allow(deprecated)] @@ -634,6 +538,7 @@ impl Error for num::TryFromIntError { } } +#[cfg(bootstrap)] #[stable(feature = "try_from", since = "1.34.0")] impl Error for array::TryFromSliceError { #[allow(deprecated)] @@ -642,6 +547,7 @@ impl Error for array::TryFromSliceError { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for num::ParseFloatError { #[allow(deprecated)] @@ -650,6 +556,7 @@ impl Error for num::ParseFloatError { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for string::FromUtf8Error { #[allow(deprecated)] @@ -658,6 +565,7 @@ impl Error for string::FromUtf8Error { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for string::FromUtf16Error { #[allow(deprecated)] @@ -666,6 +574,7 @@ impl Error for string::FromUtf16Error { } } +#[cfg(bootstrap)] #[stable(feature = "str_parse_error2", since = "1.8.0")] impl Error for Infallible { fn description(&self) -> &str { @@ -673,6 +582,7 @@ impl Error for Infallible { } } +#[cfg(bootstrap)] #[stable(feature = "decode_utf16", since = "1.9.0")] impl Error for char::DecodeUtf16Error { #[allow(deprecated)] @@ -681,9 +591,11 @@ impl Error for char::DecodeUtf16Error { } } +#[cfg(bootstrap)] #[stable(feature = "u8_from_char", since = "1.59.0")] impl Error for char::TryFromCharError {} +#[cfg(bootstrap)] #[unstable(feature = "map_try_insert", issue = "82766")] impl<'a, K: Debug + Ord, V: Debug> Error for crate::collections::btree_map::OccupiedError<'a, K, V> @@ -694,6 +606,7 @@ impl<'a, K: Debug + Ord, V: Debug> Error } } +#[cfg(bootstrap)] #[unstable(feature = "map_try_insert", issue = "82766")] impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> { #[allow(deprecated)] @@ -702,6 +615,7 @@ impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedErr } } +#[cfg(bootstrap)] #[stable(feature = "box_error", since = "1.8.0")] impl<T: Error> Error for Box<T> { #[allow(deprecated, deprecated_in_future)] @@ -719,6 +633,7 @@ impl<T: Error> Error for Box<T> { } } +#[cfg(bootstrap)] #[unstable(feature = "thin_box", issue = "92791")] impl<T: ?Sized + crate::error::Error> crate::error::Error for crate::boxed::ThinBox<T> { fn source(&self) -> Option<&(dyn crate::error::Error + 'static)> { @@ -727,6 +642,7 @@ impl<T: ?Sized + crate::error::Error> crate::error::Error for crate::boxed::Thin } } +#[cfg(bootstrap)] #[stable(feature = "error_by_ref", since = "1.51.0")] impl<'a, T: Error + ?Sized> Error for &'a T { #[allow(deprecated, deprecated_in_future)] @@ -748,6 +664,7 @@ impl<'a, T: Error + ?Sized> Error for &'a T { } } +#[cfg(bootstrap)] #[stable(feature = "arc_error", since = "1.52.0")] impl<T: Error + ?Sized> Error for Arc<T> { #[allow(deprecated, deprecated_in_future)] @@ -769,6 +686,7 @@ impl<T: Error + ?Sized> Error for Arc<T> { } } +#[cfg(bootstrap)] #[stable(feature = "fmt_error", since = "1.11.0")] impl Error for fmt::Error { #[allow(deprecated)] @@ -777,6 +695,7 @@ impl Error for fmt::Error { } } +#[cfg(bootstrap)] #[stable(feature = "try_borrow", since = "1.13.0")] impl Error for cell::BorrowError { #[allow(deprecated)] @@ -785,6 +704,7 @@ impl Error for cell::BorrowError { } } +#[cfg(bootstrap)] #[stable(feature = "try_borrow", since = "1.13.0")] impl Error for cell::BorrowMutError { #[allow(deprecated)] @@ -793,6 +713,7 @@ impl Error for cell::BorrowMutError { } } +#[cfg(bootstrap)] #[stable(feature = "try_from", since = "1.34.0")] impl Error for char::CharTryFromError { #[allow(deprecated)] @@ -801,6 +722,7 @@ impl Error for char::CharTryFromError { } } +#[cfg(bootstrap)] #[stable(feature = "char_from_str", since = "1.20.0")] impl Error for char::ParseCharError { #[allow(deprecated)] @@ -809,12 +731,15 @@ impl Error for char::ParseCharError { } } +#[cfg(bootstrap)] #[stable(feature = "try_reserve", since = "1.57.0")] impl Error for alloc::collections::TryReserveError {} +#[cfg(bootstrap)] #[unstable(feature = "duration_checked_float", issue = "83400")] impl Error for time::FromFloatSecsError {} +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl Error for alloc::ffi::NulError { #[allow(deprecated)] @@ -823,6 +748,7 @@ impl Error for alloc::ffi::NulError { } } +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] impl From<alloc::ffi::NulError> for io::Error { /// Converts a [`alloc::ffi::NulError`] into a [`io::Error`]. @@ -831,6 +757,7 @@ impl From<alloc::ffi::NulError> for io::Error { } } +#[cfg(bootstrap)] #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] impl Error for core::ffi::FromBytesWithNulError { #[allow(deprecated)] @@ -839,12 +766,15 @@ impl Error for core::ffi::FromBytesWithNulError { } } +#[cfg(bootstrap)] #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] impl Error for core::ffi::FromBytesUntilNulError {} +#[cfg(bootstrap)] #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl Error for alloc::ffi::FromVecWithNulError {} +#[cfg(bootstrap)] #[stable(feature = "cstring_into", since = "1.7.0")] impl Error for alloc::ffi::IntoStringError { #[allow(deprecated)] @@ -857,6 +787,7 @@ impl Error for alloc::ffi::IntoStringError { } } +#[cfg(bootstrap)] impl<'a> dyn Error + 'a { /// Request a reference of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "99301")] @@ -872,6 +803,7 @@ impl<'a> dyn Error + 'a { } // Copied from `any.rs`. +#[cfg(bootstrap)] impl dyn Error + 'static { /// Returns `true` if the inner type is the same as `T`. #[stable(feature = "error_downcast", since = "1.3.0")] @@ -912,6 +844,7 @@ impl dyn Error + 'static { } } +#[cfg(bootstrap)] impl dyn Error + 'static + Send { /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] @@ -947,6 +880,7 @@ impl dyn Error + 'static + Send { } } +#[cfg(bootstrap)] impl dyn Error + 'static + Send + Sync { /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] @@ -982,6 +916,7 @@ impl dyn Error + 'static + Send + Sync { } } +#[cfg(bootstrap)] impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -1061,10 +996,12 @@ impl dyn Error { /// its sources, use `skip(1)`. #[unstable(feature = "error_iter", issue = "58520")] #[derive(Clone, Debug)] +#[cfg(bootstrap)] pub struct Chain<'a> { current: Option<&'a (dyn Error + 'static)>, } +#[cfg(bootstrap)] #[unstable(feature = "error_iter", issue = "58520")] impl<'a> Iterator for Chain<'a> { type Item = &'a (dyn Error + 'static); @@ -1076,6 +1013,7 @@ impl<'a> Iterator for Chain<'a> { } } +#[cfg(bootstrap)] impl dyn Error + Send { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -1089,6 +1027,7 @@ impl dyn Error + Send { } } +#[cfg(bootstrap)] impl dyn Error + Send + Sync { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -1246,7 +1185,7 @@ impl dyn Error + Send + Sync { /// # Err(SuperError { source: SuperErrorSideKick }) /// # } /// -/// fn main() -> Result<(), Report> { +/// fn main() -> Result<(), Report<SuperError>> { /// get_super_error()?; /// Ok(()) /// } @@ -1293,7 +1232,7 @@ impl dyn Error + Send + Sync { /// # Err(SuperError { source: SuperErrorSideKick }) /// # } /// -/// fn main() -> Result<(), Report> { +/// fn main() -> Result<(), Report<SuperError>> { /// get_super_error() /// .map_err(Report::from) /// .map_err(|r| r.pretty(true).show_backtrace(true))?; @@ -1605,72 +1544,6 @@ where } } -impl Report<Box<dyn Error>> { - fn backtrace(&self) -> Option<&Backtrace> { - // have to grab the backtrace on the first error directly since that error may not be - // 'static - let backtrace = self.error.request_ref(); - let backtrace = backtrace.or_else(|| { - self.error - .source() - .map(|source| source.chain().find_map(|source| source.request_ref())) - .flatten() - }); - backtrace - } - - /// Format the report as a single line. - #[unstable(feature = "error_reporter", issue = "90172")] - fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.error)?; - - let sources = self.error.source().into_iter().flat_map(<dyn Error>::chain); - - for cause in sources { - write!(f, ": {cause}")?; - } - - Ok(()) - } - - /// Format the report as multiple lines, with each error cause on its own line. - #[unstable(feature = "error_reporter", issue = "90172")] - fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let error = &self.error; - - write!(f, "{error}")?; - - if let Some(cause) = error.source() { - write!(f, "\n\nCaused by:")?; - - let multiple = cause.source().is_some(); - - for (ind, error) in cause.chain().enumerate() { - writeln!(f)?; - let mut indented = Indented { inner: f }; - if multiple { - write!(indented, "{ind: >4}: {error}")?; - } else { - write!(indented, " {error}")?; - } - } - } - - if self.show_backtrace { - let backtrace = self.backtrace(); - - if let Some(backtrace) = backtrace { - let backtrace = backtrace.to_string(); - - f.write_str("\n\nStack backtrace:\n")?; - f.write_str(backtrace.trim_end())?; - } - } - - Ok(()) - } -} - #[unstable(feature = "error_reporter", issue = "90172")] impl<E> From<E> for Report<E> where @@ -1682,17 +1555,6 @@ where } #[unstable(feature = "error_reporter", issue = "90172")] -impl<'a, E> From<E> for Report<Box<dyn Error + 'a>> -where - E: Error + 'a, -{ - fn from(error: E) -> Self { - let error = box error; - Report { error, show_backtrace: false, pretty: false } - } -} - -#[unstable(feature = "error_reporter", issue = "90172")] impl<E> fmt::Display for Report<E> where E: Error, @@ -1702,13 +1564,6 @@ where } } -#[unstable(feature = "error_reporter", issue = "90172")] -impl fmt::Display for Report<Box<dyn Error>> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) } - } -} - // This type intentionally outputs the same format for `Display` and `Debug`for // situations where you unwrap a `Report` or return it from main. #[unstable(feature = "error_reporter", issue = "90172")] diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index ff7fdcae16f..885e44f5e18 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -76,6 +76,15 @@ impl fmt::Debug for Error { } } +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +impl From<alloc::ffi::NulError> for Error { + /// Converts a [`alloc::ffi::NulError`] into a [`Error`]. + fn from(_: alloc::ffi::NulError) -> Error { + const_io_error!(ErrorKind::InvalidInput, "data provided contains a nul byte") + } +} + // Only derive debug in tests, to make sure it // doesn't accidentally get printed. #[cfg_attr(test, derive(Debug))] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 71bbf4317e0..dbaead406b7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -281,6 +281,9 @@ #![feature(cstr_internals)] #![feature(duration_checked_float)] #![feature(duration_constants)] +#![cfg_attr(not(bootstrap), feature(error_generic_member_access))] +#![cfg_attr(not(bootstrap), feature(error_in_core))] +#![cfg_attr(not(bootstrap), feature(error_iter))] #![feature(exact_size_is_empty)] #![feature(exclusive_wrapper)] #![feature(extend_one)] |
