Debug for the ErrorKind

One small improvement at the end of the tutorial is to fix the debug output of Func1ErrorKind. As you probably noticed, the output doesn't say much of the enum.

Debug Error:
src/main.rs:35: Func2
[…]

As a lazy shortcut, we implement Debug by calling Display and end up with

Debug Error:
src/main.rs:40: func1 error calling func2
[…}

which gives us a lot more detail.

To create your own Errors, you might find crates which create enum Display+Debug via derive macros.

Also noteworthy is custom_error to define your custom errors, which can then be used with chainerror.

use chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;

fn do_some_io() -> Result<(), Box<Error + Send + Sync>> {
    Err(io::Error::from(io::ErrorKind::NotFound))?;
    Ok(())
}

derive_str_cherr!(Func2Error);

fn func2() -> Result<(), Box<Error + Send + Sync>> {
    let filename = "foo.txt";
    do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
    Ok(())
}

enum Func1ErrorKind {
    Func2,
    IO(String),
}

impl ::std::fmt::Display for Func1ErrorKind {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match self {
            Func1ErrorKind::Func2 => write!(f, "func1 error calling func2"),
            Func1ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
        }
    }
}

impl ::std::fmt::Debug for Func1ErrorKind {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{}", self)
    }
}

impl ::std::error::Error for Func1ErrorKind {}

fn func1() -> ChainResult<(), Func1ErrorKind> {
    func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
    let filename = String::from("bar.txt");
    do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO(filename)))?;
    Ok(())
}

fn main() -> Result<(), Box<Error + Send + Sync>> {
    if let Err(e) = func1() {
        match e.kind() {
            Func1ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
            Func1ErrorKind::IO(filename) => {
                eprintln!("Main Error Report: func1 error reading '{}'", filename)
            }
        }

        if let Some(e) = e.find_chain_cause::<Func2Error>() {
            eprintln!("\nError reported by Func2Error: {}", e)
        }

        eprintln!("\nDebug Error:\n{:?}", e);
    }
    Ok(())
}
#[allow(dead_code)]
mod chainerror {
{{#includecomment ../src/lib.rs}}
}