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

Commit

Permalink
Added basic failure name (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko authored Dec 29, 2018
1 parent f121c57 commit df68d72
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 3 deletions.
4 changes: 2 additions & 2 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn bad_function() -> Result<(), WrappingError> {
}

fn main() {
for cause in Fail::iter_causes(&bad_function().unwrap_err()) {
println!("{}", cause);
for cause in Fail::iter_chain(&bad_function().unwrap_err()) {
println!("{}: {}", cause.name().unwrap_or("Error"), cause);
}
}
7 changes: 7 additions & 0 deletions failure_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern crate synstructure;
extern crate quote;

use proc_macro2::{TokenStream, Span};
use syn::LitStr;
use syn::spanned::Spanned;

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

let ty_name = LitStr::new(&s.ast().ident.to_string(), Span::call_site());

let cause_body = s.each_variant(|v| {
if let Some(cause) = v.bindings().iter().find(is_cause) {
quote!(return Some(::failure::AsFail::as_fail(#cause)))
Expand All @@ -59,6 +62,10 @@ fn fail_derive_impl(s: synstructure::Structure) -> Result<TokenStream, Error> {
let fail = s.unbound_impl(
quote!(::failure::Fail),
quote! {
fn name(&self) -> Option<&str> {
Some(concat!(module_path!(), "::", #ty_name))
}

#[allow(unreachable_code)]
fn cause(&self) -> ::failure::_core::option::Option<#make_dyn(::failure::Fail)> {
match *self { #cause_body }
Expand Down
4 changes: 4 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ with_std! {
}

impl<D: Display + Send + Sync + 'static> Fail for Context<D> {
fn name(&self) -> Option<&str> {
self.failure.as_cause().and_then(|x| x.name())
}

fn cause(&self) -> Option<&Fail> {
self.failure.as_cause()
}
Expand Down
5 changes: 5 additions & 0 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ impl Error {
self.imp.failure()
}

/// Returns the name of the underlying fail.
pub fn name(&self) -> Option<&str> {
self.as_fail().name()
}

/// Returns a reference to the underlying cause of this `Error`. Unlike the
/// method on `Fail`, this does not return an `Option`. The `Error` type
/// always has an underlying failure.
Expand Down
6 changes: 5 additions & 1 deletion src/error_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ struct ErrorMessage<D: Display + Debug + Sync + Send + 'static> {
msg: D,
}

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

impl<D: Display + Debug + Sync + Send + 'static> Display for ErrorMessage<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ with_std! {
/// `std::error::Error`, and are also `Send`, `Sync`, and `'static`, implement
/// `Fail` by a blanket impl.
pub trait Fail: Display + Debug + Send + Sync + 'static {
/// Returns the "name" of the error.
///
/// This is typically the type name. Not all errors will implement
/// this. This method is expected to be most useful in situations
/// where errors need to be reported to external instrumentation systems
/// such as crash reporters.
fn name(&self) -> Option<&str> {
None
}

/// Returns a reference to the underlying cause of this failure, if it
/// is an error that wraps other errors.
///
Expand Down
21 changes: 21 additions & 0 deletions tests/basic_fail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#[macro_use]
extern crate failure;

use failure::Fail;

#[test]
fn test_name() {
#[derive(Fail, Debug)]
#[fail(display = "my error")]
struct MyError;

let err = MyError;

assert_eq!(err.to_string(), "my error");
assert_eq!(err.name(), Some("basic_fail::MyError"));

let ctx = err.context("whatever");

assert_eq!(ctx.to_string(), "whatever");
assert_eq!(ctx.name(), Some("basic_fail::MyError"));
}

0 comments on commit df68d72

Please sign in to comment.