From 2e3e5c9d15e234495369e9b47d032644dd5664ad Mon Sep 17 00:00:00 2001 From: Bennett Hardwick Date: Thu, 29 Jun 2023 11:58:35 +1000 Subject: [PATCH] feat(protocol): add StdError impl for Box (#273) --- src/protocol.rs | 24 ++++++++--- tests/test_derive_source_chain.rs | 69 +++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 tests/test_derive_source_chain.rs diff --git a/src/protocol.rs b/src/protocol.rs index 7531db1f..f516984f 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -69,14 +69,26 @@ pub trait Diagnostic: std::error::Error { } } -impl std::error::Error for Box { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - (**self).source() +macro_rules! box_impls { + ($($box_type:ty),*) => { + $( + impl std::error::Error for $box_type { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + (**self).source() + } + + fn cause(&self) -> Option<&dyn std::error::Error> { + self.source() + } + } + )* } +} - fn cause(&self) -> Option<&dyn std::error::Error> { - self.source() - } +box_impls! { + Box, + Box, + Box } impl From diff --git a/tests/test_derive_source_chain.rs b/tests/test_derive_source_chain.rs new file mode 100644 index 00000000..fb7ddb24 --- /dev/null +++ b/tests/test_derive_source_chain.rs @@ -0,0 +1,69 @@ +use std::sync::Arc; + +use miette::{miette, Diagnostic}; +use thiserror::Error; + +#[test] +fn test_source() { + #[derive(Debug, Diagnostic, Error)] + #[error("Bar")] + struct Bar; + + #[derive(Debug, Diagnostic, Error)] + #[error("Foo")] + struct Foo { + #[source] + bar: Bar, + } + + let e = miette!(Foo { bar: Bar }); + let mut chain = e.chain(); + + assert_eq!("Foo", chain.next().unwrap().to_string()); + assert_eq!("Bar", chain.next().unwrap().to_string()); + assert!(chain.next().is_none()); +} + +#[test] +fn test_source_boxed() { + #[derive(Debug, Diagnostic, Error)] + #[error("Bar")] + struct Bar; + + #[derive(Debug, Diagnostic, Error)] + #[error("Foo")] + struct Foo { + #[source] + bar: Box, + } + + let error = miette!(Foo { bar: Box::new(Bar) }); + + let mut chain = error.chain(); + + assert_eq!("Foo", chain.next().unwrap().to_string()); + assert_eq!("Bar", chain.next().unwrap().to_string()); + assert!(chain.next().is_none()); +} + +#[test] +fn test_source_arc() { + #[derive(Debug, Diagnostic, Error)] + #[error("Bar")] + struct Bar; + + #[derive(Debug, Diagnostic, Error)] + #[error("Foo")] + struct Foo { + #[source] + bar: Arc, + } + + let error = miette!(Foo { bar: Arc::new(Bar) }); + + let mut chain = error.chain(); + + assert_eq!("Foo", chain.next().unwrap().to_string()); + assert_eq!("Bar", chain.next().unwrap().to_string()); + assert!(chain.next().is_none()); +}