Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit df68d72

Browse files
authored
Added basic failure name (#289)
1 parent f121c57 commit df68d72

File tree

7 files changed

+54
-3
lines changed

7 files changed

+54
-3
lines changed

examples/simple.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn bad_function() -> Result<(), WrappingError> {
1616
}
1717

1818
fn main() {
19-
for cause in Fail::iter_causes(&bad_function().unwrap_err()) {
20-
println!("{}", cause);
19+
for cause in Fail::iter_chain(&bad_function().unwrap_err()) {
20+
println!("{}: {}", cause.name().unwrap_or("Error"), cause);
2121
}
2222
}

failure_derive/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ extern crate synstructure;
77
extern crate quote;
88

99
use proc_macro2::{TokenStream, Span};
10+
use syn::LitStr;
1011
use syn::spanned::Spanned;
1112

1213
#[derive(Debug)]
@@ -40,6 +41,8 @@ fn fail_derive_impl(s: synstructure::Structure) -> Result<TokenStream, Error> {
4041
quote! { & }
4142
};
4243

44+
let ty_name = LitStr::new(&s.ast().ident.to_string(), Span::call_site());
45+
4346
let cause_body = s.each_variant(|v| {
4447
if let Some(cause) = v.bindings().iter().find(is_cause) {
4548
quote!(return Some(::failure::AsFail::as_fail(#cause)))
@@ -59,6 +62,10 @@ fn fail_derive_impl(s: synstructure::Structure) -> Result<TokenStream, Error> {
5962
let fail = s.unbound_impl(
6063
quote!(::failure::Fail),
6164
quote! {
65+
fn name(&self) -> Option<&str> {
66+
Some(concat!(module_path!(), "::", #ty_name))
67+
}
68+
6269
#[allow(unreachable_code)]
6370
fn cause(&self) -> ::failure::_core::option::Option<#make_dyn(::failure::Fail)> {
6471
match *self { #cause_body }

src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ with_std! {
108108
}
109109

110110
impl<D: Display + Send + Sync + 'static> Fail for Context<D> {
111+
fn name(&self) -> Option<&str> {
112+
self.failure.as_cause().and_then(|x| x.name())
113+
}
114+
111115
fn cause(&self) -> Option<&Fail> {
112116
self.failure.as_cause()
113117
}

src/error/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ impl Error {
7070
self.imp.failure()
7171
}
7272

73+
/// Returns the name of the underlying fail.
74+
pub fn name(&self) -> Option<&str> {
75+
self.as_fail().name()
76+
}
77+
7378
/// Returns a reference to the underlying cause of this `Error`. Unlike the
7479
/// method on `Fail`, this does not return an `Option`. The `Error` type
7580
/// always has an underlying failure.

src/error_message.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ struct ErrorMessage<D: Display + Debug + Sync + Send + 'static> {
1919
msg: D,
2020
}
2121

22-
impl<D: Display + Debug + Sync + Send + 'static> Fail for ErrorMessage<D> { }
22+
impl<D: Display + Debug + Sync + Send + 'static> Fail for ErrorMessage<D> {
23+
fn name(&self) -> Option<&str> {
24+
Some("failure::ErrorMessage")
25+
}
26+
}
2327

2428
impl<D: Display + Debug + Sync + Send + 'static> Display for ErrorMessage<D> {
2529
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ with_std! {
106106
/// `std::error::Error`, and are also `Send`, `Sync`, and `'static`, implement
107107
/// `Fail` by a blanket impl.
108108
pub trait Fail: Display + Debug + Send + Sync + 'static {
109+
/// Returns the "name" of the error.
110+
///
111+
/// This is typically the type name. Not all errors will implement
112+
/// this. This method is expected to be most useful in situations
113+
/// where errors need to be reported to external instrumentation systems
114+
/// such as crash reporters.
115+
fn name(&self) -> Option<&str> {
116+
None
117+
}
118+
109119
/// Returns a reference to the underlying cause of this failure, if it
110120
/// is an error that wraps other errors.
111121
///

tests/basic_fail.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#[macro_use]
2+
extern crate failure;
3+
4+
use failure::Fail;
5+
6+
#[test]
7+
fn test_name() {
8+
#[derive(Fail, Debug)]
9+
#[fail(display = "my error")]
10+
struct MyError;
11+
12+
let err = MyError;
13+
14+
assert_eq!(err.to_string(), "my error");
15+
assert_eq!(err.name(), Some("basic_fail::MyError"));
16+
17+
let ctx = err.context("whatever");
18+
19+
assert_eq!(ctx.to_string(), "whatever");
20+
assert_eq!(ctx.name(), Some("basic_fail::MyError"));
21+
}

0 commit comments

Comments
 (0)