From 73c0582f67b42641f331bf8c54e0ce4e01b9dd85 Mon Sep 17 00:00:00 2001 From: "james.baker@helsing.ai" Date: Tue, 2 May 2023 11:27:21 +0100 Subject: [PATCH] Automatically convert to external errors A pattern documented by thiserror is ``` pub enum MyError { ... #[error(transparent)] Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error } ``` It'd be nice for this to work with ensure! but right now, that macro returns an eyre error. With this PR, the macro additionally runs an .into(). In the case that the return type is an eyre error, obviously .into() will do nothing and be compiled away. In the case that there is a from method, the wrapping will occur. This enables eyre to be used for ergonomic 'implementation detail error' in a thiserror using system which has contractual errors. --- src/macros.rs | 12 ++++++------ tests/test_macros.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 792a646..5062ca0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -51,13 +51,13 @@ #[macro_export] macro_rules! bail { ($msg:literal $(,)?) => { - return $crate::private::Err($crate::eyre!($msg)); + return $crate::private::Err($crate::eyre!($msg).into()); }; ($err:expr $(,)?) => { - return $crate::private::Err($crate::eyre!($err)); + return $crate::private::Err($crate::eyre!($err).into()); }; ($fmt:expr, $($arg:tt)*) => { - return $crate::private::Err($crate::eyre!($fmt, $($arg)*)); + return $crate::private::Err($crate::eyre!($fmt, $($arg)*).into()); }; } @@ -109,17 +109,17 @@ macro_rules! bail { macro_rules! ensure { ($cond:expr, $msg:literal $(,)?) => { if !$cond { - return $crate::private::Err($crate::eyre!($msg)); + return $crate::private::Err($crate::eyre!($msg).into()); } }; ($cond:expr, $err:expr $(,)?) => { if !$cond { - return $crate::private::Err($crate::eyre!($err)); + return $crate::private::Err($crate::eyre!($err).into()); } }; ($cond:expr, $fmt:expr, $($arg:tt)*) => { if !$cond { - return $crate::private::Err($crate::eyre!($fmt, $($arg)*)); + return $crate::private::Err($crate::eyre!($fmt, $($arg)*).into()); } }; } diff --git a/tests/test_macros.rs b/tests/test_macros.rs index abcc3c9..a3d33d2 100644 --- a/tests/test_macros.rs +++ b/tests/test_macros.rs @@ -39,6 +39,22 @@ fn test_ensure() { Ok(()) }; assert!(f().is_err()); + + let f = || -> Result<(), SomeWrappingErr> { + ensure!(false, "this will fail"); + Ok(()) + }; + assert!(f().is_err()); +} + +struct SomeWrappingErr { + err: eyre::Error, +} + +impl From for SomeWrappingErr { + fn from(err: eyre::Error) -> Self { + SomeWrappingErr { err } + } } #[test]