Support any source() that derefs to std::error::Error

This commit is contained in:
David Tolnay 2019-10-09 07:33:17 -07:00
parent bb13f4b07a
commit 761ff1c708
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
3 changed files with 34 additions and 2 deletions

View File

@ -35,10 +35,11 @@ fn struct_error(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
}; };
let source_method = source.map(|source| { let source_method = source.map(|source| {
let member = quote_spanned!(source.span()=> &self.#source); let member = quote_spanned!(source.span()=> self.#source);
quote! { quote! {
fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
std::option::Option::Some(#member) use thiserror::private::AsDynError;
std::option::Option::Some(#member.as_dyn_error())
} }
} }
}); });

23
src/aserror.rs Normal file
View File

@ -0,0 +1,23 @@
use std::error::Error;
pub trait AsDynError {
fn as_dyn_error(&self) -> &(dyn Error + 'static);
}
impl<T: Error + 'static> AsDynError for T {
fn as_dyn_error(&self) -> &(dyn Error + 'static) {
self
}
}
impl AsDynError for dyn Error + 'static {
fn as_dyn_error(&self) -> &(dyn Error + 'static) {
self
}
}
impl AsDynError for dyn Error + Send + Sync + 'static {
fn as_dyn_error(&self) -> &(dyn Error + 'static) {
self
}
}

View File

@ -1 +1,9 @@
mod aserror;
pub use thiserror_impl::*; pub use thiserror_impl::*;
// Not public API.
#[doc(hidden)]
pub mod private {
pub use crate::aserror::AsDynError;
}