From 22b95121c993eb9a862a8add0fa6f7feab3095dd Mon Sep 17 00:00:00 2001 From: Johnathan Sharratt Date: Sat, 7 Aug 2021 09:50:57 +0200 Subject: [PATCH 1/2] Added the Sync trait constraint on errors so that they work across thread boundaries which is a common case in tokio --- src/error_chain.rs | 8 ++++---- src/lib.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/error_chain.rs b/src/error_chain.rs index 83827096..d14b576e 100644 --- a/src/error_chain.rs +++ b/src/error_chain.rs @@ -231,7 +231,7 @@ macro_rules! impl_error_chain_processed { fn with_chain(error: E, kind: K) -> Self - where E: ::std::error::Error + Send + 'static, + where E: ::std::error::Error + Send + Sync + 'static, K: Into { Self::with_chain(error, kind) @@ -273,7 +273,7 @@ macro_rules! impl_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: ::std::error::Error + Send + Sync + 'static, K: Into<$error_kind_name> { $error_name::with_boxed_chain(Box::new(error), kind) @@ -281,7 +281,7 @@ macro_rules! impl_error_chain_processed { /// Construct a chained error from another boxed error and a kind, and generates a backtrace #[allow(unknown_lints, bare_trait_objects)] - pub fn with_boxed_chain(error: Box<::std::error::Error + Send>, kind: K) + pub fn with_boxed_chain(error: Box<::std::error::Error + Send + Sync>, kind: K) -> $error_name where K: Into<$error_kind_name> { @@ -426,7 +426,7 @@ macro_rules! impl_error_chain_processed { EK: Into<$error_kind_name>; } - impl $result_ext_name for ::std::result::Result where E: ::std::error::Error + Send + 'static { + impl $result_ext_name for ::std::result::Result where E: ::std::error::Error + Send + Sync + 'static { fn chain_err(self, callback: F) -> ::std::result::Result where F: FnOnce() -> EK, EK: Into<$error_kind_name> { diff --git a/src/lib.rs b/src/lib.rs index 43d2d5f4..2f1d75de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -592,7 +592,7 @@ impl<'a> Iterator for Iter<'a> { /// This trait is implemented on all the errors generated by the `error_chain` /// macro. -pub trait ChainedError: error::Error + Send + 'static { +pub trait ChainedError: error::Error + Send + Sync + 'static { /// Associated kind type. type ErrorKind; @@ -605,7 +605,7 @@ pub trait ChainedError: error::Error + Send + 'static { fn with_chain(error: E, kind: K) -> Self where Self: Sized, - E: ::std::error::Error + Send + 'static, + E: ::std::error::Error + Send + Sync + 'static, K: Into; /// Returns the kind of the error. @@ -675,7 +675,7 @@ where #[allow(unknown_lints, bare_trait_objects)] pub struct State { /// Next error in the error chain. - pub next_error: Option>, + pub next_error: Option>, /// Backtrace for the current error. pub backtrace: InternalBacktrace, } @@ -692,7 +692,7 @@ impl Default for State { impl State { /// Creates a new State type #[allow(unknown_lints, bare_trait_objects)] - pub fn new(e: Box) -> State { + pub fn new(e: Box) -> State { let backtrace = CE::extract_backtrace(&*e).unwrap_or_else(InternalBacktrace::new); State { next_error: Some(e), From 264cd11bdc7b4a68c72e8b8b72b76de2ff2a9042 Mon Sep 17 00:00:00 2001 From: Johnathan Sharratt Date: Sat, 7 Aug 2021 11:03:19 +0200 Subject: [PATCH 2/2] Added the sync trait as an optional feature --- CHANGELOG.md | 3 +++ Cargo.toml | 8 +++++--- src/error_chain.rs | 17 ++++++++++------- src/lib.rs | 12 ++++++++---- src/trait_alias.rs | 23 +++++++++++++++++++++++ 5 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 src/trait_alias.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index bd82afc3..c135225d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 0.12.5 +- [Added the 'Sync' trait so that errors can propogate across threads (e.g. usage within tokio)](https://github.com/john-sharratt/error-chain) + # 0.12.4 - [executable bits to support build platform linters](https://github.com/rust-lang-nursery/error-chain/pull/289) diff --git a/Cargo.toml b/Cargo.toml index 77b622e4..1c0f4130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "error-chain" -version = "0.12.4" # remember to update html_root_url +version = "0.12.5" # remember to update html_root_url authors = [ "Brian Anderson ", "Paul Colomiets ", "Colin Kiegel ", "Yamakaky ", - "Andrew Gauger "] + "Andrew Gauger ", + "Johnathan Sharratt "] description = "Yet another error boilerplate library." keywords = ["error"] categories = ["rust-patterns"] @@ -17,8 +18,9 @@ readme = "README.md" license = "MIT/Apache-2.0" [features] -default = ["backtrace", "example_generated"] +default = ["backtrace", "example_generated", "sync"] example_generated = [] +sync = [] [dependencies] backtrace = { version = "0.3.3", optional = true } diff --git a/src/error_chain.rs b/src/error_chain.rs index d14b576e..d83f7473 100644 --- a/src/error_chain.rs +++ b/src/error_chain.rs @@ -218,7 +218,10 @@ macro_rules! impl_error_chain_processed { pub $crate::State, ); - impl $crate::ChainedError for $error_name { + impl $crate::trait_alias::TraitCheck for $error_name { } + + impl $crate::ChainedError for $error_name + { type ErrorKind = $error_kind_name; fn new(kind: $error_kind_name, state: $crate::State) -> $error_name { @@ -231,7 +234,7 @@ macro_rules! impl_error_chain_processed { fn with_chain(error: E, kind: K) -> Self - where E: ::std::error::Error + Send + Sync + 'static, + where E: $crate::trait_alias::StdError + 'static, K: Into { Self::with_chain(error, kind) @@ -273,15 +276,15 @@ macro_rules! impl_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 + Sync + 'static, + where E: $crate::trait_alias::StdError + 'static, K: Into<$error_kind_name> { $error_name::with_boxed_chain(Box::new(error), kind) } - + /// Construct a chained error from another boxed error and a kind, and generates a backtrace #[allow(unknown_lints, bare_trait_objects)] - pub fn with_boxed_chain(error: Box<::std::error::Error + Send + Sync>, kind: K) + pub fn with_boxed_chain(error: $crate::trait_alias::BoxError, kind: K) -> $error_name where K: Into<$error_kind_name> { @@ -290,7 +293,7 @@ macro_rules! impl_error_chain_processed { $crate::State::new::<$error_name>(error, ), ) } - + /// Returns the kind of the error. pub fn kind(&self) -> &$error_kind_name { &self.0 @@ -426,7 +429,7 @@ macro_rules! impl_error_chain_processed { EK: Into<$error_kind_name>; } - impl $result_ext_name for ::std::result::Result where E: ::std::error::Error + Send + Sync + 'static { + impl $result_ext_name for ::std::result::Result where E: $crate::trait_alias::StdError + 'static { fn chain_err(self, callback: F) -> ::std::result::Result where F: FnOnce() -> EK, EK: Into<$error_kind_name> { diff --git a/src/lib.rs b/src/lib.rs index 2f1d75de..bfa07e8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -553,6 +553,8 @@ pub use quick_main::ExitCode; mod backtrace; #[cfg(feature = "example_generated")] pub mod example_generated; +#[doc(hidden)] +pub mod trait_alias; pub use backtrace::Backtrace; #[doc(hidden)] pub use backtrace::InternalBacktrace; @@ -592,7 +594,9 @@ impl<'a> Iterator for Iter<'a> { /// This trait is implemented on all the errors generated by the `error_chain` /// macro. -pub trait ChainedError: error::Error + Send + Sync + 'static { +pub trait ChainedError: crate::trait_alias::StdError + 'static +where Self: crate::trait_alias::TraitCheck +{ /// Associated kind type. type ErrorKind; @@ -605,7 +609,7 @@ pub trait ChainedError: error::Error + Send + Sync + 'static { fn with_chain(error: E, kind: K) -> Self where Self: Sized, - E: ::std::error::Error + Send + Sync + 'static, + E: crate::trait_alias::StdError + 'static, K: Into; /// Returns the kind of the error. @@ -675,7 +679,7 @@ where #[allow(unknown_lints, bare_trait_objects)] pub struct State { /// Next error in the error chain. - pub next_error: Option>, + pub next_error: Option, /// Backtrace for the current error. pub backtrace: InternalBacktrace, } @@ -692,7 +696,7 @@ impl Default for State { impl State { /// Creates a new State type #[allow(unknown_lints, bare_trait_objects)] - pub fn new(e: Box) -> State { + pub fn new(e: trait_alias::BoxError) -> State { let backtrace = CE::extract_backtrace(&*e).unwrap_or_else(InternalBacktrace::new); State { next_error: Some(e), diff --git a/src/trait_alias.rs b/src/trait_alias.rs new file mode 100644 index 00000000..687b25ed --- /dev/null +++ b/src/trait_alias.rs @@ -0,0 +1,23 @@ +#[doc(hidden)] +#[cfg(feature = "sync")] +pub trait StdError: std::error::Error + Send + Sync { } +#[doc(hidden)] +#[cfg(not(feature = "sync"))] +pub trait StdError: std::error::Error + Send { } +#[cfg(feature = "sync")] +impl StdError for E where E: std::error::Error + Send + Sync { } +#[cfg(not(feature = "sync"))] +impl StdError for E where E: std::error::Error + Send { } +#[doc(hidden)] +#[cfg(feature = "sync")] +pub type BoxError = Box; +#[doc(hidden)] +#[cfg(not(feature = "sync"))] +pub type BoxError = Box; + +#[doc(hidden)] +#[cfg(feature = "sync")] +pub trait TraitCheck: Send + Sync { } +#[doc(hidden)] +#[cfg(not(feature = "sync"))] +pub trait TraitCheck: Send { } \ No newline at end of file