From 87adfd3661efcb5e632a7e3be90a18fb31f41b67 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 19 May 2024 14:41:58 -0700 Subject: [PATCH 1/3] break: Use manual impls instead of thiserror This commit removes the heavy thiserror dependency by replacing its automatically generated implementations with manually written ones. Hopefully the newly written implementations are identical to the previous ones, but just in case I've marked this as a breaking change. Since there is already a breaking change on master this shouldn't be a big deal. Closes #126 Signed-off-by: John Nunley --- Cargo.toml | 1 - src/error.rs | 56 +++++++++++++++++++++++++++++++++++------- src/sources/channel.rs | 16 ++++++++++-- src/sources/ping.rs | 17 +++++++++++-- 4 files changed, 76 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 61bd4975..4fcef2c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ pin-utils = { version = "0.1.0", optional = true } polling = "3.0.0" slab = "0.4.8" rustix = { version = "0.38", default-features = false, features = ["event", "fs", "pipe", "std"] } -thiserror = "1.0.7" [target.'cfg(unix)'.dependencies] nix = { version = "0.28", default-features = false, features = ["signal"], optional = true } diff --git a/src/error.rs b/src/error.rs index 7a6001b8..0e146f08 100644 --- a/src/error.rs +++ b/src/error.rs @@ -20,25 +20,44 @@ use std::fmt::{self, Debug, Formatter}; /// The primary error type used by Calloop covering internal errors and I/O /// errors that arise during loop operations such as source registration or /// event dispatching. -#[derive(thiserror::Error, Debug)] +#[derive(Debug)] pub enum Error { /// When an event source is registered (or re- or un-registered) with the /// event loop, this error variant will occur if the token Calloop uses to /// keep track of the event source is not valid. - #[error("invalid token provided to internal function")] InvalidToken, /// This variant wraps a [`std::io::Error`], which might arise from /// Calloop's internal operations. - #[error("underlying IO error")] - IoError(#[from] std::io::Error), + IoError(std::io::Error), /// Any other unexpected error kind (most likely from a user implementation of /// [`EventSource::process_events()`]) will be wrapped in this. /// /// [`EventSource::process_events()`]: crate::EventSource::process_events() - #[error("other error during loop operation")] - OtherError(#[from] Box), + OtherError(Box), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidToken => f.write_str("invalid token provided to internal function"), + Self::IoError(err) => write!(f, "underlying IO error: {}", err), + Self::OtherError(err) => write!(f, "other error during loop operation: {}", err), + } + } +} + +impl From for Error { + fn from(value: std::io::Error) -> Self { + Self::IoError(value) + } +} + +impl From> for Error { + fn from(value: Box) -> Self { + Self::OtherError(value) + } } impl From for std::io::Error { @@ -52,17 +71,24 @@ impl From for std::io::Error { } } +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidToken => None, + Self::IoError(err) => Some(err), + Self::OtherError(err) => Some(&**err), + } + } +} + /// [`Result`] alias using Calloop's error type. pub type Result = core::result::Result; /// An error generated when trying to insert an event source -#[derive(thiserror::Error)] -#[error("error inserting event source")] pub struct InsertError { /// The source that could not be inserted pub inserted: T, /// The generated error - #[source] pub error: Error, } @@ -73,6 +99,12 @@ impl Debug for InsertError { } } +impl fmt::Display for InsertError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "error inserting event source: {}", &self.error) + } +} + impl From> for crate::Error { /// Converts the [`InsertError`] into Calloop's error type, throwing away /// the contained source. @@ -81,3 +113,9 @@ impl From> for crate::Error { e.error } } + +impl std::error::Error for InsertError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&self.error) + } +} diff --git a/src/sources/channel.rs b/src/sources/channel.rs index 58e5e842..dc297884 100644 --- a/src/sources/channel.rs +++ b/src/sources/channel.rs @@ -8,6 +8,7 @@ //! A synchronous version of the channel is provided by [`sync_channel`], in which //! the [`SyncSender`] will block when the channel is full. +use std::fmt; use std::sync::mpsc; use crate::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; @@ -213,10 +214,21 @@ impl EventSource for Channel { } /// An error arising from processing events for a channel. -#[derive(thiserror::Error, Debug)] -#[error(transparent)] +#[derive(Debug)] pub struct ChannelError(PingError); +impl fmt::Display for ChannelError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl std::error::Error for ChannelError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&self.0) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/sources/ping.rs b/src/sources/ping.rs index f986a83d..0752f6c6 100644 --- a/src/sources/ping.rs +++ b/src/sources/ping.rs @@ -32,6 +32,8 @@ mod pipe; #[cfg(not(any(target_os = "linux", windows)))] use pipe as platform; +use std::fmt; + /// Create a new ping event source /// /// you are given a [`Ping`] instance, which can be cloned and used to ping the @@ -56,10 +58,21 @@ pub type Ping = platform::Ping; pub type PingSource = platform::PingSource; /// An error arising from processing events for a ping. -#[derive(thiserror::Error, Debug)] -#[error(transparent)] +#[derive(Debug)] pub struct PingError(Box); +impl fmt::Display for PingError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl std::error::Error for PingError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&*self.0) + } +} + #[cfg(test)] mod tests { use crate::transient::TransientSource; From a239fb6f852c65ffaf2192d3d6fca96a7ee0612b Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 19 May 2024 14:53:33 -0700 Subject: [PATCH 2/3] m: Fix thiserror for non-optional features Signed-off-by: John Nunley --- src/sources/futures.rs | 27 ++++++++++++++++++++++----- src/sources/signals.rs | 16 ++++++++++++++-- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/sources/futures.rs b/src/sources/futures.rs index 0bf7c552..bc5b180b 100644 --- a/src/sources/futures.rs +++ b/src/sources/futures.rs @@ -22,6 +22,7 @@ use async_task::{Builder, Runnable}; use slab::Slab; use std::{ cell::RefCell, + fmt, future::Future, rc::Rc, sync::{ @@ -248,10 +249,17 @@ impl Drop for Executor { /// Error generated when trying to schedule a future after the /// executor was destroyed. -#[derive(thiserror::Error, Debug)] -#[error("the executor was destroyed")] +#[derive(Debug)] pub struct ExecutorDestroyed; +impl fmt::Display for ExecutorDestroyed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("the executor was destroyed") + } +} + +impl std::error::Error for ExecutorDestroyed {} + /// Create a new executor, and its associated scheduler /// /// May fail due to OS errors preventing calloop to setup its internal pipes (if your @@ -371,17 +379,26 @@ impl EventSource for Executor { } /// An error arising from processing events in an async executor event source. -#[derive(thiserror::Error, Debug)] +#[derive(Debug)] pub enum ExecutorError { /// Error while reading new futures added via [`Scheduler::schedule()`]. - #[error("error adding new futures")] NewFutureError(ChannelError), /// Error while processing wake events from existing futures. - #[error("error processing wake events")] WakeError(PingError), } +impl fmt::Display for ExecutorError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::NewFutureError(err) => write!(f, "error adding new futures: {}", err), + Self::WakeError(err) => write!(f, "error processing wake events: {}", err), + } + } +} + +impl std::error::Error for ExecutorError {} + #[cfg(test)] mod tests { use super::*; diff --git a/src/sources/signals.rs b/src/sources/signals.rs index 0cba53f9..6707aed1 100644 --- a/src/sources/signals.rs +++ b/src/sources/signals.rs @@ -11,6 +11,7 @@ //! they'll inherit their parent signal mask. use std::convert::TryFrom; +use std::fmt; use std::io::Error as IoError; use std::os::raw::c_int; @@ -331,6 +332,17 @@ impl EventSource for Signals { } /// An error arising from processing events for a process signal. -#[derive(thiserror::Error, Debug)] -#[error(transparent)] +#[derive(Debug)] pub struct SignalError(Box); + +impl fmt::Display for SignalError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl std::error::Error for SignalError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&*self.0) + } +} From 73a7564f37062273e3f72927c0bb3a9c7bf79821 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 19 May 2024 15:01:56 -0700 Subject: [PATCH 3/3] fix: Add coverage(off) to new error methods Signed-off-by: John Nunley --- src/error.rs | 7 +++++++ src/sources/channel.rs | 2 ++ src/sources/futures.rs | 2 ++ src/sources/ping.rs | 2 ++ src/sources/signals.rs | 2 ++ 5 files changed, 15 insertions(+) diff --git a/src/error.rs b/src/error.rs index 0e146f08..7fab6f4c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -39,6 +39,7 @@ pub enum Error { } impl fmt::Display for Error { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::InvalidToken => f.write_str("invalid token provided to internal function"), @@ -49,12 +50,14 @@ impl fmt::Display for Error { } impl From for Error { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn from(value: std::io::Error) -> Self { Self::IoError(value) } } impl From> for Error { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn from(value: Box) -> Self { Self::OtherError(value) } @@ -62,6 +65,7 @@ impl From> for Error { impl From for std::io::Error { /// Converts Calloop's error type into a [`std::io::Error`]. + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn from(err: Error) -> Self { match err { Error::IoError(source) => source, @@ -72,6 +76,7 @@ impl From for std::io::Error { } impl std::error::Error for Error { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::InvalidToken => None, @@ -100,6 +105,7 @@ impl Debug for InsertError { } impl fmt::Display for InsertError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "error inserting event source: {}", &self.error) } @@ -115,6 +121,7 @@ impl From> for crate::Error { } impl std::error::Error for InsertError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.error) } diff --git a/src/sources/channel.rs b/src/sources/channel.rs index dc297884..c48f70e3 100644 --- a/src/sources/channel.rs +++ b/src/sources/channel.rs @@ -218,12 +218,14 @@ impl EventSource for Channel { pub struct ChannelError(PingError); impl fmt::Display for ChannelError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } impl std::error::Error for ChannelError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } diff --git a/src/sources/futures.rs b/src/sources/futures.rs index bc5b180b..ea2b4e5f 100644 --- a/src/sources/futures.rs +++ b/src/sources/futures.rs @@ -253,6 +253,7 @@ impl Drop for Executor { pub struct ExecutorDestroyed; impl fmt::Display for ExecutorDestroyed { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("the executor was destroyed") } @@ -389,6 +390,7 @@ pub enum ExecutorError { } impl fmt::Display for ExecutorError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::NewFutureError(err) => write!(f, "error adding new futures: {}", err), diff --git a/src/sources/ping.rs b/src/sources/ping.rs index 0752f6c6..aa3d1eb3 100644 --- a/src/sources/ping.rs +++ b/src/sources/ping.rs @@ -62,12 +62,14 @@ pub type PingSource = platform::PingSource; pub struct PingError(Box); impl fmt::Display for PingError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } impl std::error::Error for PingError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&*self.0) } diff --git a/src/sources/signals.rs b/src/sources/signals.rs index 6707aed1..9fdddce9 100644 --- a/src/sources/signals.rs +++ b/src/sources/signals.rs @@ -336,12 +336,14 @@ impl EventSource for Signals { pub struct SignalError(Box); impl fmt::Display for SignalError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } impl std::error::Error for SignalError { + #[cfg_attr(feature = "nightly_coverage", coverage(off))] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&*self.0) }