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

Added basic failure name #289

Merged
merged 6 commits into from
Dec 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"));
}