From 982a97f1c0cd23728991010c29acc4b885085075 Mon Sep 17 00:00:00 2001 From: Izzy Swart Date: Tue, 7 Jan 2020 11:19:20 -0800 Subject: [PATCH 1/3] wip error handling --- Cargo.toml | 2 + examples/function_stream.rs | 2 +- src/channel/id_channel/mod.rs | 34 ++---------- src/channel/mod.rs | 12 ++-- src/core/data/mod.rs | 15 ++--- src/core/hal/network/mod.rs | 12 ++-- src/core/mod.rs | 35 ++++-------- src/core/orchestrator/mod.rs | 8 ++- src/format/mod.rs | 74 ++++++++++++------------- src/kind/array.rs | 13 +++-- src/kind/{failure_error.rs => error.rs} | 30 +++++----- src/kind/mod.rs | 24 ++++---- src/kind/result.rs | 15 ++--- src/lib.rs | 8 +-- 14 files changed, 121 insertions(+), 163 deletions(-) rename src/kind/{failure_error.rs => error.rs} (70%) diff --git a/Cargo.toml b/Cargo.toml index 458bb67..27a51be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ void = "1.0.2" downcast-rs = "1.1.1" weak-table = "0.2.3" url = "2.1.0" +thiserror = "1.0.9" +anyhow = "1.0.26" [target.wasm32-unknown-unknown.dependencies] wasm-bindgen = { version = "0.2.54", optional = true } diff --git a/examples/function_stream.rs b/examples/function_stream.rs index 02c968f..de263d9 100644 --- a/examples/function_stream.rs +++ b/examples/function_stream.rs @@ -6,7 +6,7 @@ use vessels::{ log, OnTo, }; -use failure::Error; +use anyhow::Error; use futures::{stream::iter, StreamExt}; diff --git a/src/channel/id_channel/mod.rs b/src/channel/id_channel/mod.rs index 84b3212..b89a1b4 100644 --- a/src/channel/id_channel/mod.rs +++ b/src/channel/id_channel/mod.rs @@ -21,6 +21,7 @@ use futures::{ }; use serde::{de::DeserializeOwned, Serialize}; use std::{collections::HashMap, sync::Mutex}; +use thiserror::Error; use crate::{ channel::{Channel, Context as IContext, Fork as IFork, ForkHandle, Waiter}, @@ -84,41 +85,14 @@ impl Display for SinkStage { } } -#[derive(Debug)] +#[derive(Debug, Error)] pub enum IdChannelError { + #[error("send on underlying channel `{1}` in `{0}` stage failed: `{2}`")] Channel(SinkStage, ForkHandle, ChannelError), + #[error("underlying channel `{0}` does not exist")] InvalidId(ForkHandle), } -impl Fail for IdChannelError { - fn name(&self) -> Option<&str> { - Some("IdChannelError") - } - fn cause(&self) -> Option<&dyn Fail> { - if let IdChannelError::Channel(_, _, error) = self { - return Some(error.0.as_fail()); - } - None - } -} - -impl Display for IdChannelError { - fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { - use IdChannelError::{Channel, InvalidId}; - write!( - formatter, - "{}", - match self { - Channel(stage, handle, error) => format!( - "send on underlying channel {} in {} stage failed: {}", - handle, stage, error - ), - InvalidId(handle) => format!("underlying channel {} does not exist", handle), - } - ) - } -} - impl Drop for IdChannel { fn drop(&mut self) { self.in_channels.lock().unwrap().remove(&ForkHandle(0)); diff --git a/src/channel/mod.rs b/src/channel/mod.rs index 0718bd8..7a66801 100644 --- a/src/channel/mod.rs +++ b/src/channel/mod.rs @@ -6,16 +6,14 @@ use crate::{ Kind, }; -use core::{ - fmt::{self, Display, Formatter}, - marker::Unpin, -}; -use failure::{Error, Fail}; +use anyhow::Error; +use core::fmt::{self, Display, Formatter}; use futures::{Sink, Stream}; use serde::{ de::{DeserializeOwned, DeserializeSeed}, Deserialize, Serialize, }; +use thiserror::Error; #[derive(Serialize, Deserialize, Debug, PartialEq, Hash, Eq, Clone, Copy)] #[repr(transparent)] @@ -32,8 +30,8 @@ pub trait Fork: Sync + Send + 'static { fn get_fork(&self, fork_ref: ForkHandle) -> Fallible; } -#[derive(Debug, Fail)] -pub struct ChannelError(#[fail(cause)] pub(crate) Error); +#[derive(Debug, Error)] +pub struct ChannelError(#[source] pub(crate) Error); impl Display for ChannelError { fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { diff --git a/src/core/data/mod.rs b/src/core/data/mod.rs index eb301bd..bbf37a7 100644 --- a/src/core/data/mod.rs +++ b/src/core/data/mod.rs @@ -9,9 +9,10 @@ use crate::{ Kind, }; +use anyhow::{anyhow, Error}; use core::fmt::{self, Debug, Formatter}; -use failure::{format_err, Error, Fail}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use thiserror::Error; #[derive(Hash, Kind, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Checksum(pub(crate) [u8; 32]); @@ -48,17 +49,17 @@ pub struct Resource { acquire: Option Infallible> + Sync + Send>>, } -#[derive(Fail, Kind)] -#[fail(display = "reification failed: {}", cause)] +#[derive(Error, Kind)] +#[error("reification failed: {source}")] pub struct ReifyError { - #[fail(cause)] - cause: Error, + #[source] + source: Error, pub resource: Resource, } impl Debug for ReifyError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "ReifyError {{ cause: {:?} }}", self.cause) + write!(f, "ReifyError {{ source: {:?} }}", self.source) } } @@ -92,7 +93,7 @@ impl Resource { } else { // TODO reify from abstract acquisition methods Err(ReifyError { - cause: format_err!("no suitable acquisition method"), + source: anyhow!("no suitable acquisition method"), resource: self, }) } diff --git a/src/core/hal/network/mod.rs b/src/core/hal/network/mod.rs index 0e67d77..2e51889 100644 --- a/src/core/hal/network/mod.rs +++ b/src/core/hal/network/mod.rs @@ -6,9 +6,11 @@ use crate::{ object, Kind, }; -use failure::{Error, Fail}; +use anyhow::Error; +use failure::Fail; use futures::{future::ready, lock::Mutex, FutureExt, Sink, StreamExt}; use std::{net::SocketAddr, sync::Arc}; +use thiserror::Error; use url::Url; #[object] @@ -43,10 +45,10 @@ impl FromTransportError for ListenError { } } -#[derive(Fail, Debug, Kind)] -#[fail(display = "connection failed while open: {}", cause)] +#[derive(Error, Debug, Kind)] +#[error("connection failed while open: {cause}")] pub struct ConnectionError { - #[fail(cause)] + #[source] cause: Error, } @@ -123,7 +125,7 @@ impl Server { ) -> Future> where T: ApplyEncode<'a>, - >::Item>>::Error: Fail, + >::Item>>::Error: std::error::Error + Sync + Send + 'static, { let handler = Arc::new(Mutex::new(handler)); self.0.listen( diff --git a/src/core/mod.rs b/src/core/mod.rs index b0466fa..a296729 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,11 +1,12 @@ use alloc::sync::Arc; -#[cfg(any(feature = "core", target_arch = "wasm32"))] +use anyhow::Error; +#[cfg(target_arch = "wasm32")] use core::any::Any; -use core::fmt::{self, Display, Formatter}; -use failure::{Error, Fail}; +use failure::Fail; use futures::{lock, SinkExt, StreamExt}; use lazy_static::lazy_static; use std::{collections::HashMap, sync::Mutex}; +use thiserror::Error; use crate::{ channel::IdChannel, @@ -32,28 +33,16 @@ pub struct UnimplementedError { feature: String, } -#[derive(Fail, Debug, Kind)] +#[derive(Error, Debug, Kind)] pub enum CoreError { + #[error("feature unavailable or unregistered")] Unavailable, - Unimplemented(#[fail(cause)] UnimplementedError), - Construct(#[fail(cause)] Error), - Transport(#[fail(cause)] Error), -} - -impl Display for CoreError { - fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { - use CoreError::{Construct, Transport, Unavailable, Unimplemented}; - write!( - formatter, - "{}", - match self { - Unavailable => "this feature is unavailable or unregistered".to_owned(), - Unimplemented(feature) => format!("{}", feature), - Construct(e) => format!("handle transfer failed: {}", e), - Transport(e) => format!("underlying transport failed: {}", e), - } - ) - } + #[error("`{0}`")] + Unimplemented(#[source] UnimplementedError), + #[error("`handle transfer failed: {0}`")] + Construct(#[source] Error), + #[error("`underlying transport failed: {0}`")] + Transport(#[source] Error), } impl FromTransportError for CoreError { diff --git a/src/core/orchestrator/mod.rs b/src/core/orchestrator/mod.rs index 214ca04..c31da93 100644 --- a/src/core/orchestrator/mod.rs +++ b/src/core/orchestrator/mod.rs @@ -11,12 +11,14 @@ use crate::{ Kind, }; +use anyhow::Error; use core::marker::PhantomData; -use failure::{Error, Fail}; +use failure::Fail; use futures::SinkExt; #[cfg(feature = "core")] use futures::StreamExt; use serde::{Deserialize, Serialize}; +use thiserror::Error; #[cfg(all(not(target_arch = "wasm32"), feature = "core"))] mod native; @@ -65,8 +67,8 @@ trait OrchestratorInner { #[derive(Kind)] pub struct Orchestrator(Shared); -#[derive(Fail, Debug, Kind)] -#[fail(display = "instantiate failed: {}", cause)] +#[derive(Error, Debug, Kind)] +#[error("instantiate failed: {cause}")] pub struct InstantiateError { cause: Error, } diff --git a/src/format/mod.rs b/src/format/mod.rs index 9ddb1f2..64d6604 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -28,9 +28,10 @@ use crate::{ use serde::{de::DeserializeSeed, Serialize}; -use core::fmt::{Debug, Display, Formatter}; +use core::fmt::{self, Debug, Formatter}; +use std::error::Error; -use failure::Fail; +use thiserror::Error; pub trait UniformStreamSink: ISink + IStream {} @@ -44,7 +45,7 @@ pub trait Format { /// binary formats and `String` for those of a human-readable nature. type Representation; /// The failure condition of this format. This may be encountered during deserialization. - type Error: Fail; + type Error: Error + Sync + Send + 'static; /// Serializes the provided item. fn serialize(item: T) -> Self::Representation @@ -62,6 +63,8 @@ pub trait Format { pub trait ApplyEncode<'de>: Sized + UniformStreamSink<>::Item> + Context<'de> +where + >::Item>>::Error: Error + 'static, { fn encode>(self) -> >::Output; } @@ -69,6 +72,7 @@ pub trait ApplyEncode<'de>: impl<'de, T> ApplyEncode<'de> for T where T: UniformStreamSink<>::Item> + Context<'de>, + >::Item>>::Error: Error + 'static, { fn encode>(self) -> >::Output { >::encode(self) @@ -82,7 +86,7 @@ pub trait ApplyDecode<'de, K: Kind> { where Self: UniformStreamSink + Sync + Send + Sized + 'static, F::Representation: Clone + Sync + Send + 'static, - >::Error: Fail, + >::Error: Error + Sync + Send + 'static, T::Item: Sync + Send + 'static; } @@ -93,7 +97,7 @@ impl<'de, U, K: Kind> ApplyDecode<'de, K> for U { where Self: UniformStreamSink + Sync + Send + Sized + 'static, F::Representation: Clone + Sync + Send, - >::Error: Fail, + >::Error: Error + Sync + Send + 'static, T::Item: Sync + Send, { >::decode::(self) @@ -102,6 +106,8 @@ impl<'de, U, K: Kind> ApplyDecode<'de, K> for U { pub trait Decode<'de, C: UniformStreamSink<::Representation> + 'static, K: Kind>: Format +where + C::Error: 'static, { type Output: IFuture>; @@ -112,6 +118,8 @@ pub trait Decode<'de, C: UniformStreamSink<::Representation> + ' pub trait Encode<'de, C: UniformStreamSink<>::Item> + Context<'de>>: Format + Sized +where + >::Item>>::Error: Error + 'static, { type Output: IStream::Representation> + ISink>::Item, C>>; @@ -127,7 +135,7 @@ impl< > Decode<'de, C, K> for T where Self::Representation: Sync + Send + Clone, - ::Representation>>::Error: Fail, + ::Representation>>::Error: Error + Sync + Send + 'static, { type Output = Fallible; @@ -167,51 +175,37 @@ where } } -pub enum EncodeError> { - Format(T::Error), - Sink(S::Error), -} - -impl + 'static> Fail for EncodeError +#[derive(Error)] +pub enum EncodeError> where - T::Error: Fail, - S::Error: Fail, + S::Error: Error + 'static, { + #[error("`{0}`")] + Format(#[source] T::Error), + #[error("`{0}`")] + Sink(#[source] S::Error), } -impl> Display for EncodeError +impl> Debug for EncodeError where - T::Error: Fail, - S::Error: Fail, + S::Error: Error + 'static, { - fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - match *self { - EncodeError::Format(ref err) => { - write!(f, "Error occurred in deserialization `{}`", err) + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + EncodeError::Format(e) => format!("Format ({:?})", e), + EncodeError::Sink(e) => format!("Sink ({:?})", e), } - EncodeError::Sink(ref err) => write!(f, "Error occurred in underlying sink `{}`", err), - } + ) } } -impl> Debug for EncodeError +impl> EncodeError where - T::Error: Fail, - S::Error: Fail, + S::Error: Error, { - fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - match *self { - EncodeError::Format(ref err) => { - write!(f, "Error occurred in deserialization `{:?}`", err) - } - EncodeError::Sink(ref err) => { - write!(f, "Error occurred in underlying sink `{:?}`", err) - } - } - } -} - -impl> EncodeError { fn from_sink_error(err: S::Error) -> Self { EncodeError::Sink(err) } @@ -228,7 +222,7 @@ impl< where T::Representation: Sync + Send + Clone, >::Item: Sync + Send, - >::Item>>::Error: Fail, + >::Item>>::Error: Error + Sync + Send + 'static, { type Output = SinkStream< Self::Representation, diff --git a/src/kind/array.rs b/src/kind/array.rs index 54627d7..29b2efd 100644 --- a/src/kind/array.rs +++ b/src/kind/array.rs @@ -6,11 +6,12 @@ use crate::{ }; use core::{mem::MaybeUninit, ptr}; -use failure::Fail; use futures::{ future::{ok, try_join_all, Ready}, FutureExt, SinkExt, StreamExt, TryFutureExt, }; +use std::error::Error; +use thiserror::Error; use void::Void; use super::WrappedError; @@ -37,11 +38,11 @@ impl Kind for [T; 0] { } } -#[derive(Fail, Debug)] -pub enum ArrayError { - #[fail(display = "{}", _0)] - Construct(#[fail(cause)] T), - #[fail(display = "expected {} elements in array, got {}", expected, got)] +#[derive(Error, Debug)] +pub enum ArrayError { + #[error("`{0}`")] + Construct(#[source] T), + #[error("expected {expected} elements in array, got {got}")] Length { got: usize, expected: usize }, } diff --git a/src/kind/failure_error.rs b/src/kind/error.rs similarity index 70% rename from src/kind/failure_error.rs rename to src/kind/error.rs index aa35667..c7becee 100644 --- a/src/kind/failure_error.rs +++ b/src/kind/error.rs @@ -6,15 +6,15 @@ use crate::{ Kind, }; +use anyhow::Error; use core::fmt::{self, Debug, Display, Formatter}; -use failure::{Error, Fail}; use futures::{SinkExt, StreamExt}; +use std::error::Error as StdError; use void::Void; #[derive(Kind)] struct ErrorShim { - name: Option, - cause: Option>, + source: Option>, debug: String, display: String, } @@ -31,22 +31,20 @@ impl Debug for ErrorShim { } } -impl Fail for ErrorShim { - fn name(&self) -> Option<&str> { - self.name.as_ref().map(|item| item.as_str()) - } - fn cause(&self) -> Option<&dyn Fail> { - self.cause.as_ref().map(|item| item.as_ref() as &dyn Fail) +impl StdError for ErrorShim { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.source + .as_ref() + .map(|item| item.as_ref() as &dyn StdError) } } -impl ErrorShim { - fn from_fail(failure: &F) -> Self { +impl From<&T> for ErrorShim { + fn from(input: &T) -> Self { ErrorShim { - name: failure.name().map(str::to_owned), - cause: failure.cause().map(|e| Box::new(ErrorShim::from_fail(e))), - debug: format!("{:?}", failure), - display: format!("{}", failure), + source: input.source().map(|e| Box::new(ErrorShim::from(e))), + debug: format!("{:?}", input), + display: format!("{}", input), } } } @@ -65,7 +63,7 @@ impl Kind for Error { ) -> Self::DeconstructFuture { Box::pin(async move { Ok(channel - .send(channel.fork(ErrorShim::from_fail(self.as_fail())).await?) + .send(channel.fork(ErrorShim::from(&*self)).await?) .await .map_err(WrappedError::Send)?) }) diff --git a/src/kind/mod.rs b/src/kind/mod.rs index c218097..620c7f7 100644 --- a/src/kind/mod.rs +++ b/src/kind/mod.rs @@ -1,7 +1,7 @@ mod array; mod collections; mod default; -mod failure_error; +mod error; mod functions; mod future; mod iterator; @@ -23,11 +23,13 @@ pub use default::Default; pub use iterator::Iterator; pub use sink_stream::SinkStream; +use anyhow::Error; use core::pin::Pin; -use failure::{Error, Fail}; use futures::{ stream::once, Future as IFuture, FutureExt, Sink as ISink, Stream as IStream, StreamExt, }; +use std::error::Error as StdError; +use thiserror::Error; use crate::{channel::ChannelError, Kind}; @@ -100,22 +102,16 @@ impl Flatten for Stream> { pub trait AsKindMarker {} -#[derive(Fail, Debug)] -pub enum WrappedError { - #[fail(display = "{}", _0)] - Concrete(#[fail(cause)] T), - #[fail(display = "got {} items in construct, expected {}", got, expected)] +#[derive(Error, Debug)] +pub enum WrappedError { + #[error("`{0}`")] + Concrete(#[from] T), + #[error("got {got} items in construct, expected {expected}")] Insufficient { got: usize, expected: usize }, - #[fail(display = "failed to send on underlying channel: {}", _0)] + #[error("failed to send on underlying channel: `{0}`")] Send(ChannelError), } -impl From for WrappedError { - fn from(input: T) -> Self { - WrappedError::Concrete(input) - } -} - pub trait AsKind: Sized { type Kind: Kind; diff --git a/src/kind/result.rs b/src/kind/result.rs index c60b8e1..a904f7a 100644 --- a/src/kind/result.rs +++ b/src/kind/result.rs @@ -5,17 +5,18 @@ use crate::{ ConstructResult, DeconstructResult, Kind, }; -use failure::Fail; use futures::{SinkExt, StreamExt}; +use std::error::Error; +use thiserror::Error; use super::WrappedError; -#[derive(Fail, Debug)] -pub enum ResultError { - #[fail(display = "{}", _0)] - Ok(#[fail(cause)] T), - #[fail(display = "{}", _0)] - Err(#[fail(cause)] E), +#[derive(Error, Debug)] +pub enum ResultError { + #[error("`{0}`")] + Ok(#[source] T), + #[error("`{0}`")] + Err(#[source] E), } #[kind] diff --git a/src/lib.rs b/src/lib.rs index e48c255..b6337cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,9 +19,9 @@ pub mod reflect; pub mod replicate; use ::core::any::Any; +use std::error::Error; use downcast_rs::{impl_downcast, Downcast}; use erased_serde::Serialize as ErasedSerialize; -use failure::Fail; use futures::Future; use serde::{de::DeserializeOwned, Serialize}; @@ -159,7 +159,7 @@ pub trait Kind: Any + Sized + Sync + Send + Unpin + 'static { /// from deconstruction. type ConstructItem: Serialize + DeserializeOwned + Send + Sync + Unpin + 'static; /// The failure condition of constructing a concrete type from communicated data. - type ConstructError: Fail; + type ConstructError: Error + Sync + Send + 'static; /// The concrete future type returned by the construction process. type ConstructFuture: Future> + Sync + Send + 'static; @@ -174,7 +174,7 @@ pub trait Kind: Any + Sized + Sync + Send + Unpin + 'static { /// to deconstruction. type DeconstructItem: Serialize + DeserializeOwned + Send + Sync + Unpin + 'static; /// The failure condition of constructing a concrete type from communicated data. - type DeconstructError: Fail; + type DeconstructError: Error + Sync + Send + 'static; /// The concrete future type returned by the deconstruction process. This is /// used to only to communicate failure of deconstruction and does not return /// a value. @@ -224,7 +224,7 @@ macro_rules! log { #[cfg(all(feature = "core", target_arch = "wasm32"))] use { - ::core::pin::Pin, + core::pin::Pin, futures::task::{Context, Poll}, }; From 461945774a6993ce88a1452c51728dde10857116 Mon Sep 17 00:00:00 2001 From: Izzy Swart Date: Wed, 8 Jan 2020 10:54:29 -0800 Subject: [PATCH 2/3] lifetime resolution bandaid --- src/channel/id_channel/mod.rs | 1 - src/core/hal/network/mod.rs | 21 ++++++++++----------- src/core/mod.rs | 5 ++--- src/format/mod.rs | 25 ++++++++++++------------- src/lib.rs | 11 ++++++++--- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/channel/id_channel/mod.rs b/src/channel/id_channel/mod.rs index b89a1b4..85d27d1 100644 --- a/src/channel/id_channel/mod.rs +++ b/src/channel/id_channel/mod.rs @@ -12,7 +12,6 @@ use core::{ marker::PhantomData, pin::Pin, }; -use failure::Fail; use futures::{ channel::mpsc::{unbounded, SendError, UnboundedReceiver, UnboundedSender}, future::ok, diff --git a/src/core/hal/network/mod.rs b/src/core/hal/network/mod.rs index 2e51889..cb891a0 100644 --- a/src/core/hal/network/mod.rs +++ b/src/core/hal/network/mod.rs @@ -7,7 +7,6 @@ use crate::{ }; use anyhow::Error; -use failure::Fail; use futures::{future::ready, lock::Mutex, FutureExt, Sink, StreamExt}; use std::{net::SocketAddr, sync::Arc}; use thiserror::Error; @@ -16,14 +15,14 @@ use url::Url; #[object] pub trait Peer {} -#[derive(Fail, Debug, Kind)] +#[derive(Error, Debug, Kind)] pub enum ConnectError { - #[fail(display = "connection failed: {}", _0)] - Connect(#[cause] Error), - #[fail(display = "construct failed: {}", _0)] - Construct(#[cause] Error), - #[fail(display = "underlying transport failed: {}", _0)] - Transport(#[cause] Error), + #[error("connection failed: `{0}`")] + Connect(#[source] Error), + #[error("construct failed: `{0}`")] + Construct(#[source] Error), + #[error("underlying transport failed: `{0}`")] + Transport(#[source] Error), } impl FromTransportError for ConnectError { @@ -32,10 +31,10 @@ impl FromTransportError for ConnectError { } } -#[derive(Fail, Debug, Kind)] -#[fail(display = "listening failed: {}", cause)] +#[derive(Error, Debug, Kind)] +#[error("listening failed: {cause}")] pub struct ListenError { - #[fail(cause)] + #[source] cause: Error, } diff --git a/src/core/mod.rs b/src/core/mod.rs index a296729..398c3f1 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -2,7 +2,6 @@ use alloc::sync::Arc; use anyhow::Error; #[cfg(target_arch = "wasm32")] use core::any::Any; -use failure::Fail; use futures::{lock, SinkExt, StreamExt}; use lazy_static::lazy_static; use std::{collections::HashMap, sync::Mutex}; @@ -27,8 +26,8 @@ pub mod orchestrator; #[doc(hidden)] pub type Constructor = Box Infallible + Send + Sync>; -#[derive(Fail, Debug, Kind)] -#[fail(display = "{} is unimplemented on this target", feature)] +#[derive(Error, Debug, Kind)] +#[error("{feature} is unimplemented on this target")] pub struct UnimplementedError { feature: String, } diff --git a/src/format/mod.rs b/src/format/mod.rs index 64d6604..97bf7bb 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -23,13 +23,12 @@ use crate::{ channel::{Context, Shim, Target, Waiter}, core::spawn, kind::{Fallible, SinkStream}, - Kind, + ErrorBound, Kind, }; use serde::{de::DeserializeSeed, Serialize}; use core::fmt::{self, Debug, Formatter}; -use std::error::Error; use thiserror::Error; @@ -45,7 +44,7 @@ pub trait Format { /// binary formats and `String` for those of a human-readable nature. type Representation; /// The failure condition of this format. This may be encountered during deserialization. - type Error: Error + Sync + Send + 'static; + type Error: ErrorBound; /// Serializes the provided item. fn serialize(item: T) -> Self::Representation @@ -64,7 +63,7 @@ pub trait Format { pub trait ApplyEncode<'de>: Sized + UniformStreamSink<>::Item> + Context<'de> where - >::Item>>::Error: Error + 'static, + >::Item>>::Error: ErrorBound, { fn encode>(self) -> >::Output; } @@ -72,7 +71,7 @@ where impl<'de, T> ApplyEncode<'de> for T where T: UniformStreamSink<>::Item> + Context<'de>, - >::Item>>::Error: Error + 'static, + >::Item>>::Error: ErrorBound, { fn encode>(self) -> >::Output { >::encode(self) @@ -86,7 +85,7 @@ pub trait ApplyDecode<'de, K: Kind> { where Self: UniformStreamSink + Sync + Send + Sized + 'static, F::Representation: Clone + Sync + Send + 'static, - >::Error: Error + Sync + Send + 'static, + >::Error: ErrorBound, T::Item: Sync + Send + 'static; } @@ -97,7 +96,7 @@ impl<'de, U, K: Kind> ApplyDecode<'de, K> for U { where Self: UniformStreamSink + Sync + Send + Sized + 'static, F::Representation: Clone + Sync + Send, - >::Error: Error + Sync + Send + 'static, + >::Error: ErrorBound, T::Item: Sync + Send, { >::decode::(self) @@ -119,7 +118,7 @@ where pub trait Encode<'de, C: UniformStreamSink<>::Item> + Context<'de>>: Format + Sized where - >::Item>>::Error: Error + 'static, + >::Item>>::Error: ErrorBound, { type Output: IStream::Representation> + ISink>::Item, C>>; @@ -135,7 +134,7 @@ impl< > Decode<'de, C, K> for T where Self::Representation: Sync + Send + Clone, - ::Representation>>::Error: Error + Sync + Send + 'static, + ::Representation>>::Error: ErrorBound, { type Output = Fallible; @@ -178,7 +177,7 @@ where #[derive(Error)] pub enum EncodeError> where - S::Error: Error + 'static, + S::Error: ErrorBound, { #[error("`{0}`")] Format(#[source] T::Error), @@ -188,7 +187,7 @@ where impl> Debug for EncodeError where - S::Error: Error + 'static, + S::Error: ErrorBound, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( @@ -204,7 +203,7 @@ where impl> EncodeError where - S::Error: Error, + S::Error: ErrorBound, { fn from_sink_error(err: S::Error) -> Self { EncodeError::Sink(err) @@ -222,7 +221,7 @@ impl< where T::Representation: Sync + Send + Clone, >::Item: Sync + Send, - >::Item>>::Error: Error + Sync + Send + 'static, + >::Item>>::Error: ErrorBound, { type Output = SinkStream< Self::Representation, diff --git a/src/lib.rs b/src/lib.rs index b6337cf..00f0d05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,11 +19,11 @@ pub mod reflect; pub mod replicate; use ::core::any::Any; -use std::error::Error; use downcast_rs::{impl_downcast, Downcast}; use erased_serde::Serialize as ErasedSerialize; use futures::Future; use serde::{de::DeserializeOwned, Serialize}; +use std::error::Error; /// Generates an implementation of `Kind` for trait objects. /// @@ -159,7 +159,7 @@ pub trait Kind: Any + Sized + Sync + Send + Unpin + 'static { /// from deconstruction. type ConstructItem: Serialize + DeserializeOwned + Send + Sync + Unpin + 'static; /// The failure condition of constructing a concrete type from communicated data. - type ConstructError: Error + Sync + Send + 'static; + type ConstructError: ErrorBound; /// The concrete future type returned by the construction process. type ConstructFuture: Future> + Sync + Send + 'static; @@ -174,7 +174,7 @@ pub trait Kind: Any + Sized + Sync + Send + Unpin + 'static { /// to deconstruction. type DeconstructItem: Serialize + DeserializeOwned + Send + Sync + Unpin + 'static; /// The failure condition of constructing a concrete type from communicated data. - type DeconstructError: Error + Sync + Send + 'static; + type DeconstructError: ErrorBound; /// The concrete future type returned by the deconstruction process. This is /// used to only to communicate failure of deconstruction and does not return /// a value. @@ -195,6 +195,11 @@ pub trait Kind: Any + Sized + Sync + Send + Unpin + 'static { /// by `Kind`. pub(crate) trait SerdeAny: erased_serde::Serialize + Downcast + Sync + Send {} +#[doc(hidden)] +pub trait ErrorBound: Error + Sync + Send + 'static {} + +impl ErrorBound for T {} + impl_downcast!(SerdeAny); serialize_trait_object!(SerdeAny); From f8b3ec2f1040f5444195ff25fc85daaa9cc7507f Mon Sep 17 00:00:00 2001 From: Izzy Swart Date: Wed, 8 Jan 2020 11:07:43 -0800 Subject: [PATCH 3/3] eliminate failure --- Cargo.toml | 1 - src/core/hal/network/web.rs | 6 ++--- src/core/mod.rs | 2 +- src/core/orchestrator/mod.rs | 5 ++-- src/lib.rs | 2 +- src/reflect/mod.rs | 45 +++++++++++++----------------------- 6 files changed, 23 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 27a51be..e3f670d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ default = ["cbor", "json", "bincode"] [dependencies] futures = { version = "0.3.1", features = ["thread-pool"] } serde = { version = "1.0.101", features = ["derive"] } -failure = "0.1.5" erased-serde = "0.3.9" serde_json = { version = "1.0.41", optional = true } serde_cbor = "0.10.2" diff --git a/src/core/hal/network/web.rs b/src/core/hal/network/web.rs index e5568b3..ee9e729 100644 --- a/src/core/hal/network/web.rs +++ b/src/core/hal/network/web.rs @@ -2,7 +2,6 @@ use super::{ConnectError, ConnectionError, RawClient}; use crate::{core::spawn, kind::Future, kind::SinkStream, SyncSendAssert}; -use failure::Fail; use futures::{ channel::{ mpsc::{unbounded, UnboundedReceiver}, @@ -12,13 +11,14 @@ use futures::{ }; use js_sys::Uint8Array; use url::Url; +use thiserror::Error; use wasm_bindgen::{closure::Closure, JsCast}; use web_sys::{BinaryType, MessageEvent, WebSocket}; pub(crate) struct Client; -#[derive(Fail, Debug)] -#[fail(display = "the target port is being blocked")] +#[derive(Error, Debug)] +#[error("the target port is being blocked")] pub struct SecurityError; impl RawClient for Client { diff --git a/src/core/mod.rs b/src/core/mod.rs index 398c3f1..f04344b 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,6 +1,6 @@ use alloc::sync::Arc; use anyhow::Error; -#[cfg(target_arch = "wasm32")] +#[cfg(any(target_arch = "wasm32", feature = "core"))] use core::any::Any; use futures::{lock, SinkExt, StreamExt}; use lazy_static::lazy_static; diff --git a/src/core/orchestrator/mod.rs b/src/core/orchestrator/mod.rs index c31da93..8795825 100644 --- a/src/core/orchestrator/mod.rs +++ b/src/core/orchestrator/mod.rs @@ -13,7 +13,6 @@ use crate::{ use anyhow::Error; use core::marker::PhantomData; -use failure::Fail; use futures::SinkExt; #[cfg(feature = "core")] use futures::StreamExt; @@ -43,8 +42,8 @@ impl Module { #[kind(using::Serde)] pub(crate) struct LocalModule(pub(crate) Checksum); -#[derive(Fail, Debug, Kind)] -#[fail(display = "compile failed: {}", cause)] +#[derive(Error, Debug, Kind)] +#[error("compile failed: {cause}")] pub struct CompileError { cause: Error, } diff --git a/src/lib.rs b/src/lib.rs index 00f0d05..7b8314b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -229,7 +229,7 @@ macro_rules! log { #[cfg(all(feature = "core", target_arch = "wasm32"))] use { - core::pin::Pin, + ::core::pin::Pin, futures::task::{Context, Poll}, }; diff --git a/src/reflect/mod.rs b/src/reflect/mod.rs index 840c232..447adf5 100644 --- a/src/reflect/mod.rs +++ b/src/reflect/mod.rs @@ -3,7 +3,7 @@ use core::{ any::{Any, TypeId}, fmt::{self, Display, Formatter}, }; -use failure::Fail; +use thiserror::Error; pub type MethodIndex = u8; @@ -13,52 +13,39 @@ pub struct MethodTypes { pub receiver: Receiver, } -#[derive(Debug, Fail)] +#[derive(Debug, Error)] pub enum CallError { + #[error("invalid type for argument `{0}`")] Type(u8), - ArgumentCount(#[fail(cause)] ArgumentCountError), - OutOfRange(#[fail(cause)] OutOfRangeError), + #[error("`{0}`")] + ArgumentCount(#[source] ArgumentCountError), + #[error("`{0}`")] + OutOfRange(#[source] OutOfRangeError), + #[error("expected `{0}` receiver")] IncorrectReceiver(Receiver), } -impl Display for CallError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - use CallError::{ArgumentCount, IncorrectReceiver, OutOfRange, Type}; - - write!( - f, - "{}", - match self { - Type(position) => format!("invalid type for argument {}", position), - OutOfRange(error) => format!("{}", error), - ArgumentCount(error) => format!("{}", error), - IncorrectReceiver(expected) => format!("expected {} receiver", expected), - } - ) - } -} - -#[derive(Debug, Fail)] -#[fail(display = "method {} out of range", index)] +#[derive(Debug, Error)] +#[error("method {index} out of range")] pub struct OutOfRangeError { pub index: MethodIndex, } -#[derive(Debug, Fail)] -#[fail(display = "got {} arguments, expected {}", got, expected)] +#[derive(Debug, Error)] +#[error("got {got} arguments, expected {expected}")] pub struct ArgumentCountError { pub expected: usize, pub got: usize, } -#[derive(Debug, Fail)] -#[fail(display = "no method with name {}", name)] +#[derive(Debug, Error)] +#[error("no method with name {name}")] pub struct NameError { pub name: String, } -#[derive(Debug, Fail)] -#[fail(display = "cannot cast to {:?} in this context", target)] +#[derive(Debug, Error)] +#[error("cannot cast to {target:?} in this context")] pub struct CastError { pub target: TypeId, }