diff --git a/src/no_std_error.rs b/src/no_std_error.rs index 520c11d4..d21969da 100644 --- a/src/no_std_error.rs +++ b/src/no_std_error.rs @@ -1,199 +1,45 @@ +#![allow(missing_docs)] + use core::fmt::{Debug, Display}; -/// `Error` is a trait representing the basic expectations for error values, -/// i.e., values of type `E` in `Result`. Errors must describe -/// themselves through the `Display` and `Debug` traits, and may provide -/// cause chain information: -/// -/// The [`source`] method is generally used when errors cross "abstraction -/// boundaries". If one module must report an error that is caused by an error -/// from a lower-level module, it can allow access to that error via the -/// [`source`] method. This makes it possible for the high-level module to -/// provide its own errors while also revealing some of the implementation for -/// debugging via [`source`] chains. -/// -/// [`source`]: trait.Error.html#method.source pub trait Error: Debug + Display { - /// **This method is soft-deprecated.** - /// - /// Although using it won’t cause compilation warning, - /// new code should use `Display` instead - /// and new `impl`s can omit it. - /// - /// To obtain error description as a string, use `to_string()`. - /// - /// # Examples - /// - /// ``` - /// match "xc".parse::() { - /// Err(e) => { - /// // Print `e` itself, not `e.description()`. - /// println!("Error: {}", e); - /// } - /// _ => println!("No error"), - /// } - /// ``` fn description(&self) -> &str { "description() is deprecated; use Display" } - - /// The lower-level cause of this error, if any. - /// - /// # Examples - /// - /// ``` - /// use snafu::Error; - /// use core::fmt; - /// - /// #[derive(Debug)] - /// struct SuperError { - /// side: SuperErrorSideKick, - /// } - /// - /// impl fmt::Display for SuperError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "SuperError is here!") - /// } - /// } - /// - /// impl Error for SuperError { - /// fn description(&self) -> &str { - /// "I'm the superhero of errors" - /// } - /// - /// fn cause(&self) -> Option<&dyn Error> { - /// Some(&self.side) - /// } - /// } - /// - /// #[derive(Debug)] - /// struct SuperErrorSideKick; - /// - /// impl fmt::Display for SuperErrorSideKick { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "SuperErrorSideKick is here!") - /// } - /// } - /// - /// impl Error for SuperErrorSideKick { - /// fn description(&self) -> &str { - /// "I'm SuperError side kick" - /// } - /// } - /// - /// fn get_super_error() -> Result<(), SuperError> { - /// Err(SuperError { side: SuperErrorSideKick }) - /// } - /// - /// fn main() { - /// match get_super_error() { - /// Err(e) => { - /// println!("Error: {}", e.description()); - /// println!("Caused by: {}", e.cause().unwrap()); - /// } - /// _ => println!("No error"), - /// } - /// } - /// ``` fn cause(&self) -> Option<&dyn Error> { self.source() } - - /// The lower-level source of this error, if any. - /// - /// # Examples - /// - /// ``` - /// use snafu::Error; - /// use core::fmt; - /// - /// #[derive(Debug)] - /// struct SuperError { - /// side: SuperErrorSideKick, - /// } - /// - /// impl fmt::Display for SuperError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "SuperError is here!") - /// } - /// } - /// - /// impl Error for SuperError { - /// fn description(&self) -> &str { - /// "I'm the superhero of errors" - /// } - /// - /// fn source(&self) -> Option<&(dyn Error + 'static)> { - /// Some(&self.side) - /// } - /// } - /// - /// #[derive(Debug)] - /// struct SuperErrorSideKick; - /// - /// impl fmt::Display for SuperErrorSideKick { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "SuperErrorSideKick is here!") - /// } - /// } - /// - /// impl Error for SuperErrorSideKick { - /// fn description(&self) -> &str { - /// "I'm SuperError side kick" - /// } - /// } - /// - /// fn get_super_error() -> Result<(), SuperError> { - /// Err(SuperError { side: SuperErrorSideKick }) - /// } - /// - /// fn main() { - /// match get_super_error() { - /// Err(e) => { - /// println!("Error: {}", e.description()); - /// println!("Caused by: {}", e.source().unwrap()); - /// } - /// _ => println!("No error"), - /// } - /// } - /// ``` fn source(&self) -> Option<&(dyn Error + 'static)> { None } } -impl Error for core::str::ParseBoolError { - fn description(&self) -> &str { - "failed to parse bool" +macro_rules! impl_error { + ($($e:path),*) => { + $( + impl Error for $e {} + )* } } -impl Error for core::str::Utf8Error { - fn description(&self) -> &str { - "invalid utf-8: corrupt contents" - } -} -impl Error for core::num::ParseIntError {} -impl Error for core::num::TryFromIntError {} -impl Error for core::array::TryFromSliceError {} -impl Error for core::num::ParseFloatError {} -impl Error for core::fmt::Error { - fn description(&self) -> &str { - "an error occurred when formatting an argument" - } -} -impl Error for core::cell::BorrowError { - fn description(&self) -> &str { - "already mutably borrowed" - } -} -impl Error for core::cell::BorrowMutError { - fn description(&self) -> &str { - "already borrowed" - } -} -impl Error for core::char::CharTryFromError { - fn description(&self) -> &str { - "converted integer out of range for `char`" - } -} -impl Error for core::char::ParseCharError {} + +// All errors supported by our minimum suported Rust version can be supported by +// default. +impl_error![ + core::str::ParseBoolError, // 1.0 + core::str::Utf8Error, // 1.0 + core::num::ParseIntError, // 1.0 + core::num::ParseFloatError, // 1.0 + core::char::DecodeUtf16Error, // 1.9 + core::fmt::Error, // 1.11 + core::cell::BorrowMutError, // 1.13 + core::cell::BorrowError, // 1.13 + core::char::ParseCharError // 1.20 +]; + +// We can gate these together with std futures. +#[cfg(feature = "unstable-futures")] +impl_error![ + core::num::TryFromIntError, // 1.34 + core::array::TryFromSliceError, // 1.34 + core::char::CharTryFromError // 1.34 +];