Skip to content

Commit

Permalink
feat(protocol): add StdError impl for Box<dyn Diagnostic + Send + Syn…
Browse files Browse the repository at this point in the history
…c> (#273)
  • Loading branch information
bennetthardwick committed Jun 29, 2023
1 parent 8980675 commit 2e3e5c9
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 6 deletions.
24 changes: 18 additions & 6 deletions src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,26 @@ pub trait Diagnostic: std::error::Error {
}
}

impl std::error::Error for Box<dyn Diagnostic> {
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<dyn Diagnostic>,
Box<dyn Diagnostic + Send>,
Box<dyn Diagnostic + Send + Sync>
}

impl<T: Diagnostic + Send + Sync + 'static> From<T>
Expand Down
69 changes: 69 additions & 0 deletions tests/test_derive_source_chain.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Diagnostic + Send + Sync>,
}

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<dyn Diagnostic + Send + Sync>,
}

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());
}

0 comments on commit 2e3e5c9

Please sign in to comment.