diff --git a/.travis.yml b/.travis.yml index 31d929703..a6987965f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,10 +36,15 @@ env: - secure: ncxJbvJM1vCZfcEftjsFKJMxxhKLgWKaR8Go9AMo0VB5fB2XVW/6NYO5bQEEYpOf1Nc/+2FbI2+Dkz0S/mJpUcNSfBgablCHgwU2sHse7KsoaqfHj2mf1E3exjzSHoP96hPGicC5zAjSXFjCgJPOUSGqqRaJ7z5AsJLhJT6LuK7QpvwPBZzklUN8T+n1sVmws8TNmRIbaniq/q6wYHANHcy6Dl59dx4sKwniUGiZdUhCiddVpoxbECSxc0A8mN2pk7/aW+WGxK3goBs5ZF7+JXF318F62pDcXQmR5CX6WdpenIcJ25g1Vg1WhQ4Ifpe17CN0bfxV8ShuzrQUThCDMffZCo9XySBtODdEowwK1UIpjnFLfIxjOs45Cd8o3tM2j0CfvtnjOz6BCdUU0qiwNPPNx0wFkx3ZiOfSh+FhBhvyPM12HN2tdN0esgVBItFmEci+sSIIXqjVL6DNiu5zTjbu0bs6COwlUWdmL6vmsZtq5tl7Cno9+C3szxRVAkShGydd04l9NYjqNEzTa1EPG50OsnVRKGdRiFzSxhc3BWExNKvcQ4v867t6/PpPkW6s4oXmYI3+De+8O7ExWc6a4alcrDXKlMs5fCb5Pcd4Ju9kowcjkoJo5yf2wW3Ox5R8SJpaEEpvyhx5O/qtIxjhHNzeo8Wsr/6gdNDv20r91TI= - TRAVIS_CARGO_NIGHTLY_FEATURE="" matrix: - - FEATURES=--features=backtrace - - FEATURES=--no-default-features + - FEATURES="--features=backtrace" + - FEATURES="--no-default-features --features=std" matrix: + include: + # Only test build for no_std. The smoke tests won't compile. + - script: travis-cargo build -- $FEATURES + env: FEATURES="--no-default-features" + rust: nightly exclude: - - env: FEATURES=--features=backtrace + - env: FEATURES="--features=backtrace" rust: 1.10.0 diff --git a/Cargo.toml b/Cargo.toml index 4683bf06a..7fd521443 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,9 @@ license = "MIT/Apache-2.0" travis-ci = { repository = "brson/error-chain" } [features] -default = ["backtrace", "example_generated"] +default = ["backtrace", "example_generated", "std"] example_generated = [] +std = [] [dependencies] backtrace = { version = "0.3", optional = true } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 000000000..132a07928 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,433 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits for working with Errors. +//! +//! # The `Error` trait +//! +//! `Error` is a trait representing the basic expectations for error values, +//! i.e. values of type `E` in [`Result`]. At a minimum, errors must provide +//! a description, but they may optionally provide additional detail (via +//! [`Display`]) and cause chain information: +//! +//! ``` +//! use core::fmt::Display; +//! +//! trait Error: Display { +//! fn description(&self) -> &str; +//! +//! fn cause(&self) -> Option<&Error> { None } +//! } +//! ``` +//! +//! The [`cause`] method is generally used when errors cross "abstraction +//! boundaries", i.e. when a one module must report an error that is "caused" +//! by an error from a lower-level module. This setup makes it possible for the +//! high-level module to provide its own errors that do not commit to any +//! particular implementation, but also reveal some of its implementation for +//! debugging via [`cause`] chains. +//! +//! [`Result`]: ../result/enum.Result.html +//! [`Display`]: ../fmt/trait.Display.html +//! [`cause`]: trait.Error.html#method.cause + +// This file contains the stable parts of std::error, vendored and modified +// for use in no_std environments. +// +// A note about crates and why the Error trait isn't in core to begin with: +// +// Originally, the `Error` trait was defined in libcore, and the impls +// were scattered about. However, coherence objected to this +// arrangement, because to create the blanket impls for `Box` required +// knowing that `&str: !Error`, and we have no means to deal with that +// sort of conflict just now. Therefore, for the time being, we have +// moved the `Error` trait into libstd. As we evolve a sol'n to the +// coherence challenge (e.g., specialization, neg impls, etc) we can +// reconsider what crate these items belong in. + +use core::any::TypeId; +use core::cell; +use core::fmt::{self, Debug, Display}; +use core::mem::transmute; +use core::str; +use types::boxed::Box; + +#[cfg(not(feature = "std"))] +use collections::string::{self, String}; + +#[cfg(feature = "std")] +use std::string; + +/// Base functionality for all errors in Rust. +pub trait Error: Debug + Display { + /// A short description of the error. + /// + /// The description should only be used for a simple message. + /// It should not contain newlines or sentence-ending punctuation, + /// to facilitate embedding in larger user-facing strings. + /// For showing formatted error messages with more information see + /// [`Display`]. + /// + /// [`Display`]: ../fmt/trait.Display.html + /// + /// # Examples + /// + /// ``` + /// use core::error::Error; + /// + /// match "xc".parse::() { + /// Err(e) => { + /// println!("Error: {}", e.description()); + /// } + /// _ => println!("No error"), + /// } + /// ``` + fn description(&self) -> &str; + + /// The lower-level cause of this error, if any. + /// + /// # Examples + /// + /// ``` + /// use core::error::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<&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<&Error> { None } + + /// Unstable: unclear whether to commit to this public implementation detail + fn type_id(&self) -> TypeId where Self: 'static { + TypeId::of::() + } +} + +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +impl<'a, E: Error + Send + Sync + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +impl From for Box { + fn from(err: String) -> Box { + #[derive(Debug)] + struct StringError(String); + + impl Error for StringError { + fn description(&self) -> &str { &self.0 } + } + + impl Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } + } + + Box::new(StringError(err)) + } +} + +impl From for Box { + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; + err2 + } +} + +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { + From::from(String::from(err)) + } +} + +impl<'a> From<&'a str> for Box { + fn from(err: &'a str) -> Box { + From::from(String::from(err)) + } +} + +impl Error for str::ParseBoolError { + fn description(&self) -> &str { "failed to parse bool" } +} + +impl Error for str::Utf8Error { + fn description(&self) -> &str { + "invalid utf-8: corrupt contents" + } +} + +impl Error for string::FromUtf8Error { + fn description(&self) -> &str { + "invalid utf-8" + } +} + +impl Error for string::FromUtf16Error { + fn description(&self) -> &str { + "invalid utf-16" + } +} + +impl Error for string::ParseError { + fn description(&self) -> &str { + match *self {} + } +} + +impl Error for Box { + fn description(&self) -> &str { + Error::description(&**self) + } + + fn cause(&self) -> Option<&Error> { + Error::cause(&**self) + } +} + +impl Error for fmt::Error { + fn description(&self) -> &str { + "an error occurred when formatting an argument" + } +} + +impl Error for cell::BorrowError { + fn description(&self) -> &str { + "already mutably borrowed" + } +} + +impl Error for cell::BorrowMutError { + fn description(&self) -> &str { + "already borrowed" + } +} + +// copied from any.rs +impl Error + 'static { + /// Returns true if the boxed type is the same as `T` + #[inline] + pub fn is(&self) -> bool { + // Get TypeId of the type this function is instantiated with + let t = TypeId::of::(); + + // Get TypeId of the type in the trait object + let boxed = self.type_id(); + + // Compare both TypeIds on equality + t == boxed + } + + /// Returns some reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + if self.is::() { + unsafe { + Some(&*(self as *const Error as *const T)) + } + } else { + None + } + } + + /// Returns some mutable reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.is::() { + unsafe { + Some(&mut *(self as *mut Error as *mut T)) + } + } else { + None + } + } +} + +impl Error + 'static + Send { + /// Forwards to the method defined on the type `Any`. + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `Any`. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `Any`. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +impl Error + 'static + Send + Sync { + /// Forwards to the method defined on the type `Any`. + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `Any`. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `Any`. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +impl Error { + #[inline] + /// Attempt to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + if self.is::() { + unsafe { + let raw: *mut Error = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +impl Error + Send { + #[inline] + /// Attempt to downcast the box to a concrete type. + pub fn downcast(self: Box) + -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // reapply the Send marker + transmute::, Box>(s) + }) + } +} + +impl Error + Send + Sync { + #[inline] + /// Attempt to downcast the box to a concrete type. + pub fn downcast(self: Box) + -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // reapply the Send+Sync marker + transmute::, Box>(s) + }) + } +} + +#[cfg(test)] +mod tests { + use super::Error; + use fmt; + + #[derive(Debug, PartialEq)] + struct A; + #[derive(Debug, PartialEq)] + struct B; + + impl fmt::Display for A { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "A") + } + } + impl fmt::Display for B { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "B") + } + } + + impl Error for A { + fn description(&self) -> &str { "A-desc" } + } + impl Error for B { + fn description(&self) -> &str { "A-desc" } + } + + #[test] + fn downcasting() { + let mut a = A; + let mut a = &mut a as &mut (Error + 'static); + assert_eq!(a.downcast_ref::(), Some(&A)); + assert_eq!(a.downcast_ref::(), None); + assert_eq!(a.downcast_mut::(), Some(&mut A)); + assert_eq!(a.downcast_mut::(), None); + + let a: Box = Box::new(A); + match a.downcast::() { + Ok(..) => panic!("expected error"), + Err(e) => assert_eq!(*e.downcast::().unwrap(), A), + } + } +} diff --git a/src/error_chain.rs b/src/error_chain.rs index 266ab0b8d..b6be2774a 100644 --- a/src/error_chain.rs +++ b/src/error_chain.rs @@ -30,7 +30,7 @@ macro_rules! error_chain_processed { } /// Convenient wrapper around `std::Result`. #[allow(unused)] - pub type $result_name = ::std::result::Result; + pub type $result_name = $crate::types::result::Result; }; // Without `Result` wrapper. ( @@ -86,7 +86,7 @@ macro_rules! error_chain_processed { fn with_chain(error: E, kind: K) -> Self - where E: ::std::error::Error + Send + 'static, + where E: $crate::types::error::Error + Send + 'static, K: Into { Self::with_chain(error, kind) @@ -128,12 +128,12 @@ macro_rules! error_chain_processed { /// Constructs a chained error from another error and a kind, and generates a backtrace. pub fn with_chain(error: E, kind: K) -> $error_name - where E: ::std::error::Error + Send + 'static, + where E: $crate::types::error::Error + Send + 'static, K: Into<$error_kind_name> { $error_name( kind.into(), - $crate::State::new::<$error_name>(Box::new(error), ), + $crate::State::new::<$error_name>($crate::types::boxed::Box::new(error), ), ) } @@ -159,12 +159,12 @@ macro_rules! error_chain_processed { } } - impl ::std::error::Error for $error_name { + impl $crate::types::error::Error for $error_name { fn description(&self) -> &str { self.0.description() } - fn cause(&self) -> Option<&::std::error::Error> { + fn cause(&self) -> Option<&$crate::types::error::Error> { match self.1.next_error { Some(ref c) => Some(&**c), None => { @@ -182,9 +182,9 @@ macro_rules! error_chain_processed { } } - impl ::std::fmt::Display for $error_name { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - ::std::fmt::Display::fmt(&self.0, f) + impl $crate::types::fmt::Display for $error_name { + fn fmt(&self, f: &mut $crate::types::fmt::Formatter) -> $crate::types::fmt::Result { + $crate::types::fmt::Display::fmt(&self.0, f) } } @@ -223,13 +223,13 @@ macro_rules! error_chain_processed { } } - impl From for $error_name { - fn from(s: String) -> Self { + impl From<$crate::types::string::String> for $error_name { + fn from(s: $crate::types::string::String) -> Self { $error_name::from_kind(s.into()) } } - impl ::std::ops::Deref for $error_name { + impl $crate::types::ops::Deref for $error_name { type Target = $error_kind_name; fn deref(&self) -> &Self::Target { @@ -246,8 +246,8 @@ macro_rules! error_chain_processed { #[derive(Debug)] pub enum $error_kind_name { - /// A convenient variant for String. - Msg(s: String) { + /// A convenient variant for $crate::types::string::String. + Msg(s: $crate::types::string::String) { description(&s) display("{}", s) } @@ -263,7 +263,7 @@ macro_rules! error_chain_processed { $( $(#[$meta_foreign_links])* $foreign_link_variant(err: $foreign_link_error_path) { - description(::std::error::Error::description(err)) + description($crate::types::error::Error::description(err)) display("{}", err) } ) * @@ -283,12 +283,12 @@ macro_rules! error_chain_processed { impl<'a> From<&'a str> for $error_kind_name { fn from(s: &'a str) -> Self { - $error_kind_name::Msg(s.to_string()) + $error_kind_name::Msg($crate::types::string::String::from(s)) } } - impl From for $error_kind_name { - fn from(s: String) -> Self { + impl From<$crate::types::string::String> for $error_kind_name { + fn from(s: $crate::types::string::String) -> Self { $error_kind_name::Msg(s) } } @@ -307,17 +307,17 @@ macro_rules! error_chain_processed { /// which returns *some type that can be converted to `ErrorKind`*, boxes /// the original error to store as the cause, then returns a new error /// containing the original error. - fn chain_err(self, callback: F) -> ::std::result::Result + fn chain_err(self, callback: F) -> $crate::types::result::Result where F: FnOnce() -> EK, EK: Into<$error_kind_name>; } - impl $result_ext_name for ::std::result::Result where E: ::std::error::Error + Send + 'static { - fn chain_err(self, callback: F) -> ::std::result::Result + impl $result_ext_name for $crate::types::result::Result where E: $crate::types::error::Error + Send + 'static { + fn chain_err(self, callback: F) -> $crate::types::result::Result where F: FnOnce() -> EK, EK: Into<$error_kind_name> { self.map_err(move |e| { - let state = $crate::State::new::<$error_name>(Box::new(e), ); + let state = $crate::State::new::<$error_name>($crate::types::boxed::Box::new(e), ); $crate::ChainedError::new(callback().into(), state) }) } @@ -405,7 +405,7 @@ macro_rules! impl_extract_backtrace { ($error_name: ident $error_kind_name: ident $([$link_error_path: path, $(#[$meta_links: meta])*])*) => { - fn extract_backtrace(e: &(::std::error::Error + Send + 'static)) + fn extract_backtrace(e: &($crate::types::error::Error + Send + 'static)) -> Option<::std::sync::Arc<$crate::Backtrace>> { if let Some(e) = e.downcast_ref::<$error_name>() { return e.1.backtrace.clone(); diff --git a/src/lib.rs b/src/lib.rs index e743361f3..13a5041cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,11 +61,11 @@ //! * Instead of defining the custom `Error` type as an enum, it is a //! struct containing an `ErrorKind` (which defines the //! `description` and `display` methods for the error), an opaque, -//! optional, boxed `std::error::Error + Send + 'static` object +//! optional, boxed `core::Error + Send + 'static` object //! (which defines the `cause`, and establishes the links in the //! error chain), and a `Backtrace`. //! * The macro also defines a `ResultExt` trait that defines a -//! `chain_err` method. This method on all `std::error::Error + Send + 'static` +//! `chain_err` method. This method on all `core::Error + Send + 'static` //! types extends the error chain by boxing the current //! error into an opaque object and putting it inside a new concrete //! error. @@ -86,7 +86,7 @@ //! requiring an `Into` or `From` conversion; as well as slightly //! more cumbersome to match on errors with another layer of types //! to match. -//! * Because the error type contains `std::error::Error + Send + 'static` objects, +//! * Because the error type contains `core::Error + Send + 'static` objects, //! it can't implement `PartialEq` for easy comparisons. //! //! ## Declaring error types @@ -205,7 +205,7 @@ //! //! Note that the return type is the typedef `Result`, which is //! defined by the macro as `pub type Result = -//! ::std::result::Result`. Note that in both cases +//! ::core::result::Result`. Note that in both cases //! `.into()` is called to convert a type into the `Error` type; both //! strings and `ErrorKind` have `From` conversions to turn them into //! `Error`. @@ -275,7 +275,7 @@ //! ``` //! //! `chain_err` can be called on any `Result` type where the contained -//! error type implements `std::error::Error + Send + 'static`, as long as +//! error type implements `core::Error + Send + 'static`, as long as //! the `Result` type's corresponding `ResultExt` trait is in scope. If //! the `Result` is an `Err` then `chain_err` evaluates the closure, //! which returns *some type that can be converted to `ErrorKind`*, @@ -395,9 +395,9 @@ //! `From` conversions for regular links *do not introduce a new error //! into the error chain*, while conversions for foreign links *always //! introduce a new error into the error chain*. So for the example -//! above all errors deriving from the `std::fmt::Error` type will be +//! above all errors deriving from the `core::fmt::Error` type will be //! presented to the user as a new `ErrorKind::Fmt` variant, and the -//! cause will be the original `std::fmt::Error` error. In contrast, when +//! cause will be the original `core::fmt::Error` error. In contrast, when //! `other_error::Error` is converted to `Error` the two `ErrorKind`s //! are converted between each other to create a new `Error` but the //! old error is discarded; there is no "cause" created from the @@ -420,15 +420,22 @@ //! [error-type]: https://github.com/DanielKeep/rust-error-type //! [quick-error]: https://github.com/tailhook/quick-error +#![cfg_attr(not(any(feature = "std", test)), no_std)] +#![cfg_attr(not(feature = "std"), feature(collections))] #[cfg(feature = "backtrace")] extern crate backtrace; - -use std::error; -use std::iter::Iterator; +#[cfg(not(feature = "std"))] +extern crate collections; +#[cfg(any(feature = "std", test))] +extern crate core; + +use core::iter::Iterator; +use core::fmt; +#[cfg(not(feature = "std"))] +use collections::boxed::Box; #[cfg(feature = "backtrace")] use std::sync::Arc; -use std::fmt; #[cfg(feature = "backtrace")] pub use backtrace::Backtrace; @@ -442,17 +449,22 @@ mod quick_error; mod error_chain; #[macro_use] mod quick_main; +pub mod types; + +#[cfg(not(feature = "std"))] +pub mod error; + pub use quick_main::ExitCode; #[cfg(feature = "example_generated")] pub mod example_generated; /// Iterator over the error chain using the `Error::cause()` method. -pub struct ErrorChainIter<'a>(pub Option<&'a error::Error>); +pub struct ErrorChainIter<'a>(pub Option<&'a types::error::Error>); impl<'a> Iterator for ErrorChainIter<'a> { - type Item = &'a error::Error; + type Item = &'a types::error::Error; - fn next<'b>(&'b mut self) -> Option<&'a error::Error> { + fn next<'b>(&'b mut self) -> Option<&'a types::error::Error> { match self.0.take() { Some(e) => { self.0 = e.cause(); @@ -477,7 +489,7 @@ pub fn make_backtrace() -> Option> { /// This trait is implemented on all the errors generated by the `error_chain` /// macro. -pub trait ChainedError: error::Error + Send + 'static { +pub trait ChainedError: types::error::Error + Send + 'static { /// Associated kind type. type ErrorKind; @@ -487,7 +499,7 @@ pub trait ChainedError: error::Error + Send + 'static { /// Constructs a chained error from another error and a kind, and generates a backtrace. fn with_chain(error: E, kind: K) -> Self where Self: Sized, - E: ::std::error::Error + Send + 'static, + E: types::error::Error + Send + 'static, K: Into; /// Returns the kind of the error. @@ -520,7 +532,7 @@ pub trait ChainedError: error::Error + Send + 'static { /// of the errors from `foreign_links`. #[cfg(feature = "backtrace")] #[doc(hidden)] - fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option> + fn extract_backtrace(e: &(types::error::Error + Send + 'static)) -> Option> where Self: Sized; } @@ -551,7 +563,7 @@ impl<'a, T> fmt::Display for Display<'a, T> #[doc(hidden)] pub struct State { /// Next error in the error chain. - pub next_error: Option>, + pub next_error: Option>, /// Backtrace for the current error. #[cfg(feature = "backtrace")] pub backtrace: Option>, @@ -575,7 +587,7 @@ impl Default for State { impl State { /// Creates a new State type #[cfg(feature = "backtrace")] - pub fn new(e: Box) -> State { + pub fn new(e: Box) -> State { let backtrace = CE::extract_backtrace(&*e).or_else(make_backtrace); State { next_error: Some(e), @@ -585,7 +597,7 @@ impl State { /// Creates a new State type #[cfg(not(feature = "backtrace"))] - pub fn new(e: Box) -> State { + pub fn new(e: Box) -> State { State { next_error: Some(e) } } diff --git a/src/quick_error.rs b/src/quick_error.rs index 32565ca4c..98a7eab94 100644 --- a/src/quick_error.rs +++ b/src/quick_error.rs @@ -261,9 +261,9 @@ macro_rules! quick_error { )*} ) => { #[allow(unused)] - impl ::std::fmt::Display for $name { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) - -> ::std::fmt::Result + impl $crate::types::fmt::Display for $name { + fn fmt(&self, fmt: &mut $crate::types::fmt::Formatter) + -> $crate::types::fmt::Result { match *self { $( @@ -337,19 +337,19 @@ macro_rules! quick_error { (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*} ) => { - |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| { + |quick_error!(IDENT $self_): &$name, f: &mut $crate::types::fmt::Formatter| { write!(f, $( $exprs )*) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt { display($pattern:expr) $( $tail:tt )*} ) => { - |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) } + |_, f: &mut $crate::types::fmt::Formatter| { write!(f, $pattern) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*} ) => { - |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $( $exprs )*) } + |_, f: &mut $crate::types::fmt::Formatter| { write!(f, $pattern, $( $exprs )*) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt { $t:tt $( $tail:tt )*} @@ -361,7 +361,7 @@ macro_rules! quick_error { (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt { } ) => { - |self_: &$name, f: &mut ::std::fmt::Formatter| { + |self_: &$name, f: &mut $crate::types::fmt::Formatter| { write!(f, "{}", self_.description()) } }; diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 000000000..2e52760ce --- /dev/null +++ b/src/types.rs @@ -0,0 +1,37 @@ +//! Re-exports of types for glossing over no_std/std distinctions + +/// boxed +#[cfg(not(feature = "std"))] +pub use collections::boxed; +#[cfg(feature = "std")] +pub use std::boxed; + +/// fmt +#[cfg(not(feature = "std"))] +pub use core::fmt; +#[cfg(feature = "std")] +pub use std::fmt; + +/// ops +#[cfg(not(feature = "std"))] +pub use core::ops; +#[cfg(feature = "std")] +pub use std::ops; + +/// error +#[cfg(not(feature = "std"))] +pub use error; +#[cfg(feature = "std")] +pub use std::error; + +/// result +#[cfg(not(feature = "std"))] +pub use core::result; +#[cfg(feature = "std")] +pub use std::result; + +/// string +#[cfg(not(feature = "std"))] +pub use collections::string; +#[cfg(feature = "std")] +pub use std::string;