# chainerror

`chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your binaries, you still have the error backtrace.

`chainerror` has no dependencies!

`chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace. It encapsulates all types, which have `Display + Debug` and can store the error cause internally.

Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.

Debug information is worth it!

### Features

`display-cause` : turn on printing a backtrace of the errors in `Display`

## Tutorial

Read the Tutorial

## Examples

examples/example.rs:

    // […]
    fn main() {
       if let Err(e) = func1() {
           eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
           eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
           // […]
      }
    }

    $ cargo run -q --example example
    Debug Error {:?}:
    examples/example.rs:46:13: func1 error calling func2
    Caused by:
    examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    Caused by:
    examples/example.rs:14:18: Error reading 'foo.txt'
    Caused by:
    Kind(NotFound)

    Alternative Debug Error {:#?}:
    ChainError<example::Func1Error> {
        occurrence: Some(
            "examples/example.rs:46:13",
        ),
        kind: func1 error calling func2,
        source: Some(
            ChainError<example::Func2Error> {
                occurrence: Some(
                    "examples/example.rs:21:13",
                ),
                kind: Func2Error(func2 error: calling func3),
                source: Some(
                    ChainError<alloc::string::String> {
                        occurrence: Some(
                            "examples/example.rs:14:18",
                       ),
                       kind: "Error reading \'foo.txt\'",
                        source: Some(
                            Kind(
                                NotFound,
                            ),
                        ),
                    },
                ),
            },
        ),
    }

    #![allow(unused)]
    fn main() {
    use chainerror::prelude::v1::*;
    use std::error::Error;
    use std::io;
    use std::result::Result;

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

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

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context("func1 error")?;
        Ok(())
    }

    if let Err(e) = func1() {
        #[cfg(not(windows))]
        assert_eq!(
            format!("\n{:?}\n", e),
            r#"
    src/lib.rs:21:13: func1 error
    Caused by:
    src/lib.rs:16:18: Error reading 'foo.txt'
    Caused by:
    Kind(NotFound)
    "#
        );
    }
    }

    #![allow(unused)]
    fn main() {
    use chainerror::prelude::v1::*;
    use std::error::Error;
    use std::io;
    use std::result::Result;

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

    fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
        let filename = "foo.txt";
        do_some_io().context(format!("Error reading '{}'", filename))?;
        Ok(())
    }

    derive_str_context!(Func2Error);

    fn func2() -> ChainResult<(), Func2Error> {
        func3().context(Func2Error("func2 error: calling func3".into()))?;
        Ok(())
    }

    enum Func1Error {
        Func2,
        IO(String),
    }

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

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

    fn func1() -> ChainResult<(), Func1Error> {
        func2().context(Func1Error::Func2)?;
        let filename = String::from("bar.txt");
        do_some_io().context(Func1Error::IO(filename))?;
        Ok(())
    }

    if let Err(e) = func1() {
        assert!(match e.kind() {
            Func1Error::Func2 => {
                eprintln!("Main Error Report: func1 error calling func2");
                true
            }
            Func1Error::IO(filename) => {
                eprintln!("Main Error Report: func1 error reading '{}'", filename);
                false
            }
        });

        assert!(e.find_chain_cause::<Func2Error>().is_some());

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

        assert!(e.root_cause().is_some());

        if let Some(e) = e.root_cause() {
            let io_error = e.downcast_ref::<io::Error>().unwrap();
            eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
        }

        #[cfg(not(windows))]
        assert_eq!(
            format!("\n{:?}\n", e),
            r#"
    src/lib.rs:48:13: func1 error calling func2
    Caused by:
    src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    Caused by:
    src/lib.rs:16:18: Error reading 'foo.txt'
    Caused by:
    Kind(NotFound)
    "#
        );
    }
    }

## License

Licensed under either of

- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

# Simple String Errors

An easy way of doing error handling in rust is by returning `String` as a `Box<std::error::Error>`.

If the rust `main` function returns an `Err()`, this `Err()` will be displayed with `std::fmt::Debug`.

As you can see by running the example (by pressing the "Play" button in upper right of the code block), this only prints out the last `Error`.

    Error: "func1 error"

The next chapters of this tutorial show how `chainerror` adds more information and improves inspecting the sources of an error.

You can also run the tutorial examples in the checked out chainerror git repo.

    $ cargo run -q --example tutorial1

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

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

    fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(_) = do_some_io() {
            Err("func2 error")?;
        }
        Ok(())
    }

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(_) = func2() {
            Err("func1 error")?;
        }
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        func1()
    }

# Simple Chained String Errors

With relatively small changes and the help of the `context()` method of the `chainerror` crate the `&str` errors are now chained together.

Press the play button in the upper right corner and see the nice debug output.

    use chainerror::prelude::v1::*;

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

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

    fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = do_some_io() {
            Err(e).context("func2 error")?;
        }
        Ok(())
    }

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func2() {
            Err(e).context("func1 error")?;
        }
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        func1()
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

### What did we do here?

        if let Err(e) = do_some_io() {
            Err(e).context("func2 error")?;
        }

The function `context(newerror)` stores `olderror` as the source/cause of `newerror` along with the `Location` of the `context()` call and returns `Err(newerror)`.

`?` then returns the inner error applying `.into()`, so that we again have a `Err(Box<Error + Send + Sync>)` as a result.

The `Debug` implementation of `ChainError<T>` (which is returned by `context()`) prints the `Debug` of `T` prefixed with the stored filename and line number.

`ChainError<T>` in our case is `ChainError<&str>`.

# Mapping Errors

Now let's get more rust idiomatic by using `.context()` directly on the previous `Result`.

    use chainerror::prelude::v1::*;

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

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

    fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        do_some_io().context("func2 error")?;
        Ok(())
    }

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context("func1 error")?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            eprintln!("{:?}", e);
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

If you compare the output to the previous example, you will see, that:

    Error: src/main.rs:19: "func1 error"

changed to just:

    src/main.rs:16: "func1 error"

This is, because we caught the error of `func1()` in `main()` and print it out ourselves.

We can now control, whether to output in `Debug` or `Display` mode. Maybe depending on `--debug` as a CLI argument.

# More information

To give more context to the error, you want to use `format!` to extend the information in the context string.

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

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

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

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context("func1 error")?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            eprintln!("{:?}", e);
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# The source() of Errors

Sometimes you want to inspect the `source()` of an `Error`. `chainerror` implements `std::error::Error::source()`, so you can get the cause of an error.

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

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

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

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func2() {
            if let Some(s) = e.source() {
                eprintln!("func2 failed because of '{}'", s);
                Err(e).context("func1 error")?;
            }
        }
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            eprintln!("{}", e);
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

Note, that because we changed the output of the error in `main()` from `Debug` to `Display`, we don't see the error backtrace with filename and line number.

To enable the `Display` backtrace, you have to enable the feature `display-cause` for `chainerror`.

# Downcast the Errors

`std::error::Error` comes with some helper methods to get to the original object of the `&(dyn Error + 'static)` returned by `.source()`.

    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T>
    pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T>

This is how it looks like, when using those:

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

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

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

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context("func1 error")?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            eprintln!("Error: {}", e);
            let mut s: &(dyn Error) = e.as_ref();
            while let Some(c) = s.source() {
                if let Some(ioerror) = c.downcast_ref::<io::Error>() {
                    eprintln!("caused by: std::io::Error: {}", ioerror);
                    match ioerror.kind() {
                        io::ErrorKind::NotFound => eprintln!("of kind: std::io::ErrorKind::NotFound"),
                        _ => {}
                    }
                } else {
                    eprintln!("caused by: {}", c);
                }
                s = c;
            }
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# The root cause of all Errors

`chainerror` also has some helper methods:

    fn is_chain<T: 'static + Display + Debug>(&self) -> bool
    fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>
    fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>
    fn root_cause(&self) -> Option<&(dyn Error + 'static)>
    fn find_cause<U: Error + 'static>(&self) -> Option<&U>
    fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>>
    fn kind<'a>(&'a self) -> &'a T

Using `downcast_chain_ref::<String>()` gives a `ChainError<String>`, which can be used to call `.find_cause::<io::Error>()`.

            if let Some(s) = e.downcast_chain_ref::<String>() {
                if let Some(ioerror) = s.find_cause::<io::Error>() {

or to use `.root_cause()`, which of course can be of any type implementing `std::error::Error`.

                if let Some(e) = s.root_cause() {

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

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

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

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context(format!("func1 error"))?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            eprintln!("Error: {}", e);
            if let Some(s) = e.downcast_chain_ref::<String>() {
                if let Some(ioerror) = s.find_cause::<io::Error>() {
                    eprintln!("caused by: std::io::Error: {}", ioerror);
                    match ioerror.kind() {
                        io::ErrorKind::NotFound => eprintln!("of kind: std::io::ErrorKind::NotFound"),
                        _ => {}
                    }
                }

                if let Some(e) = s.root_cause() {
                    let ioerror = e.downcast_ref::<io::Error>().unwrap();
                    eprintln!("The root cause was: std::io::Error: {:#?}", ioerror);
                }
            }
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# Finding an Error cause

To distinguish the errors occuring in various places, we can define named string errors with the "new type" pattern.

    derive_str_context!(Func2Error);
    derive_str_context!(Func1Error);

Instead of `ChainError<String>` we now have `struct Func1Error(String)` and `ChainError<Func1Error>`.

In the `main` function you can see, how we can match the different errors.

Also see:

                if let Some(f2err) = f1err.find_chain_cause::<Func2Error>() {

as a shortcut to

                if let Some(f2err) = f1err.find_cause::<ChainError<Func2Error>>() {

hiding the `ChainError<T>` implementation detail.

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

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

    derive_str_context!(Func2Error);

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

    derive_str_context!(Func1Error);

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context(Func1Error(format!("func1 error")))?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
                eprintln!("Func1Error: {}", f1err);

                if let Some(f2err) = f1err.find_cause::<ChainError<Func2Error>>() {
                    eprintln!("Func2Error: {}", f2err);
                }

                if let Some(f2err) = f1err.find_chain_cause::<Func2Error>() {
                    eprintln!("Debug Func2Error:\n{:?}", f2err);
                }
            }
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# Selective Error Handling

What about functions returning different Error types?

In this example `func1()` can return either `Func1ErrorFunc2` or `Func1ErrorIO`.

We might want to `match` on `func1()` with something like:

    fn main() -> Result<(), Box<Error + Send + Sync>> {
        match func1() {
            Err(e) if let Some(s) = e.downcast_chain_ref::<Func1ErrorIO>() =>
            eprintln!("Func1ErrorIO:\n{:?}", s),

            Err(e) if let Some(s) = e.downcast_chain_ref::<Func1ErrorFunc2>() =>
            eprintln!("Func1ErrorFunc2:\n{:?}", s),

            Ok(_) => {},
        }
        Ok(())
    }

but this is not valid rust code, so we end up doing it the hard way. In the next chapter, we will see, how to solve this more elegantly.

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

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

    derive_str_context!(Func2Error);

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

    derive_str_context!(Func1ErrorFunc2);
    derive_str_context!(Func1ErrorIO);

    fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        func2().context(Func1ErrorFunc2(format!("func1 error calling func2")))?;
        let filename = "bar.txt";
        do_some_io().context(Func1ErrorIO(format!("Error reading '{}'", filename)))?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
        if let Err(e) = func1() {
            if let Some(s) = e.downcast_ref::<ChainError<Func1ErrorIO>>() {
                eprintln!("Func1ErrorIO:\n{:?}", s);
            }

            if let Some(s) = e.downcast_chain_ref::<Func1ErrorFunc2>() {
                eprintln!("Func1ErrorFunc2:\n{:?}", s);
            }
            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# ErrorKind to the rescue

To cope with different kind of errors, we introduce the kind of an error `Func1ErrorKind` with an enum.

Because we derive `Debug` and implement `Display` our `Func1ErrorKind` enum, this enum can be used as a `std::error::Error`.

Only returning `Func1ErrorKind` in `func1()` now let us get rid of `Result<(), Box<Error + Send + Sync>>` and we can use `ChainResult<(), Func1ErrorKind>`.

In `main` we can now directly use the methods of `ChainError<T>` without downcasting the error first.

Also a nice `match` on `ChainError<T>.kind()` is now possible, which returns `&T`, meaning `&Func1ErrorKind` here.

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

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

    derive_str_context!(Func2Error);

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

    #[derive(Debug)]
    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::error::Error for Func1ErrorKind {}

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

    fn main() -> Result<(), Box<dyn 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);

            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# Debug for the ErrorKind

One small improvement 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::prelude::v1::*;
    use std::error::Error;
    use std::io;
    use std::result::Result;

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

    derive_str_context!(Func2Error);

    fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        let filename = "foo.txt";
        do_some_io().context(Func2Error(format!("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().context(Func1ErrorKind::Func2)?;
        let filename = String::from("bar.txt");
        do_some_io().context(Func1ErrorKind::IO(filename))?;
        Ok(())
    }

    fn main() -> Result<(), Box<dyn 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);

            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# Deref for the ErrorKind

Because ChainError<T> implements Deref to &T, we can also match on `*e` instead of `e.kind()` or call a function with `&e`

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

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

    derive_str_context!(Func2Error);

    fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        let filename = "foo.txt";
        do_some_io().context(Func2Error(format!("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().context(Func1ErrorKind::Func2)?;
        let filename = String::from("bar.txt");
        do_some_io().context(Func1ErrorKind::IO(filename))?;
        Ok(())
    }

    fn handle_func1errorkind(e: &Func1ErrorKind) {
        match e {
            Func1ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
            Func1ErrorKind::IO(ref filename) => {
                eprintln!("Main Error Report: func1 error reading '{}'", filename)
            }
        }
    }

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

            handle_func1errorkind(&e);

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

            eprintln!("\nDebug Error:\n{:?}", e);

            std::process::exit(1);
        }
        Ok(())
    }
    #[allow(dead_code)]
    mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }

# Writing a library

I would advise to only expose an `mycrate::ErrorKind` and type alias `mycrate::Error` to `ChainError<mycrate::ErrorKind>` so you can tell your library users to use the `.kind()` method as `std::io::Error` does.

If you later decide to make your own `Error` implementation, your library users don't have to change much or anything.

    #[allow(dead_code)]
    #[macro_use]
    pub mod chainerror {
    //! `chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
    //! binaries, you still have the error backtrace.
    //!
    //! `chainerror` has no dependencies!
    //!
    //! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
    //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
    //!
    //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
    //!
    //! Debug information is worth it!
    //!
    //! ## Features
    //!
    //! `display-cause`
    //! : turn on printing a backtrace of the errors in `Display`
    //!
    //! # Tutorial
    //!
    //! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
    //!
    //! # Examples
    //!
    //! examples/example.rs:
    //! ```rust,ignore
    //! // […]
    //! fn main() {
    //!    if let Err(e) = func1() {
    //!        eprintln!("\nDebug Error {{:?}}:\n{:?}", e);
    //!        eprintln!("\nAlternative Debug Error {{:#?}}:\n{:#?}\n", e);
    //!        // […]
    //!   }
    //! }
    //! ```
    //!
    //! ```console
    //! $ cargo run -q --example example
    //! Debug Error {:?}:
    //! examples/example.rs:46:13: func1 error calling func2
    //! Caused by:
    //! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! examples/example.rs:14:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //!
    //! Alternative Debug Error {:#?}:
    //! ChainError<example::Func1Error> {
    //!     occurrence: Some(
    //!         "examples/example.rs:46:13",
    //!     ),
    //!     kind: func1 error calling func2,
    //!     source: Some(
    //!         ChainError<example::Func2Error> {
    //!             occurrence: Some(
    //!                 "examples/example.rs:21:13",
    //!             ),
    //!             kind: Func2Error(func2 error: calling func3),
    //!             source: Some(
    //!                 ChainError<alloc::string::String> {
    //!                     occurrence: Some(
    //!                         "examples/example.rs:14:18",
    //!                    ),
    //!                    kind: "Error reading \'foo.txt\'",
    //!                     source: Some(
    //!                         Kind(
    //!                             NotFound,
    //!                         ),
    //!                     ),
    //!                 },
    //!             ),
    //!         },
    //!     ),
    //! }
    //! ```
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     func2().context("func1 error")?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:21:13: func1 error
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```
    //!
    //!
    //! ```rust
    //! use chainerror::prelude::v1::*;
    //! use std::error::Error;
    //! use std::io;
    //! use std::result::Result;
    //!
    //! fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     Err(io::Error::from(io::ErrorKind::NotFound))?;
    //!     Ok(())
    //! }
    //!
    //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
    //!     let filename = "foo.txt";
    //!     do_some_io().context(format!("Error reading '{}'", filename))?;
    //!     Ok(())
    //! }
    //!
    //! derive_str_context!(Func2Error);
    //!
    //! fn func2() -> ChainResult<(), Func2Error> {
    //!     func3().context(Func2Error("func2 error: calling func3".into()))?;
    //!     Ok(())
    //! }
    //!
    //! enum Func1Error {
    //!     Func2,
    //!     IO(String),
    //! }
    //!
    //! impl ::std::fmt::Display for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         match self {
    //!             Func1Error::Func2 => write!(f, "func1 error calling func2"),
    //!             Func1Error::IO(filename) => write!(f, "Error reading '{}'", filename),
    //!         }
    //!     }
    //! }
    //!
    //! impl ::std::fmt::Debug for Func1Error {
    //!     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
    //!         write!(f, "{}", self)
    //!     }
    //! }
    //!
    //! fn func1() -> ChainResult<(), Func1Error> {
    //!     func2().context(Func1Error::Func2)?;
    //!     let filename = String::from("bar.txt");
    //!     do_some_io().context(Func1Error::IO(filename))?;
    //!     Ok(())
    //! }
    //!
    //! if let Err(e) = func1() {
    //!     assert!(match e.kind() {
    //!         Func1Error::Func2 => {
    //!             eprintln!("Main Error Report: func1 error calling func2");
    //!             true
    //!         }
    //!         Func1Error::IO(filename) => {
    //!             eprintln!("Main Error Report: func1 error reading '{}'", filename);
    //!             false
    //!         }
    //!     });
    //!
    //!     assert!(e.find_chain_cause::<Func2Error>().is_some());
    //!
    //!     if let Some(e) = e.find_chain_cause::<Func2Error>() {
    //!         eprintln!("\nError reported by Func2Error: {}", e)
    //!     }
    //!
    //!     assert!(e.root_cause().is_some());
    //!
    //!     if let Some(e) = e.root_cause() {
    //!         let io_error = e.downcast_ref::<io::Error>().unwrap();
    //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
    //!     }
    //!
    //!     #[cfg(not(windows))]
    //!     assert_eq!(
    //!         format!("\n{:?}\n", e),
    //!         r#"
    //! src/lib.rs:48:13: func1 error calling func2
    //! Caused by:
    //! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
    //! Caused by:
    //! src/lib.rs:16:18: Error reading 'foo.txt'
    //! Caused by:
    //! Kind(NotFound)
    //! "#
    //!     );
    //! }
    //! #    else {
    //! #        unreachable!();
    //! #    }
    //! ```

    #![deny(clippy::all)]
    #![deny(clippy::integer_arithmetic)]
    #![deny(missing_docs)]

    use std::any::TypeId;
    use std::error::Error;
    use std::fmt::{Debug, Display, Formatter, Result};
    use std::panic::Location;

    pub mod prelude {
        //! convenience prelude
        pub mod v1 {
            //! convenience prelude
            pub use super::super::ChainErrorDown as _;
            pub use super::super::ResultTrait as _;
            pub use super::super::{ChainError, ChainResult};
            pub use crate::{derive_err_kind, derive_str_context};
        }
    }

    /// chains an inner error kind `T` with a causing error
    pub struct ChainError<T> {
        occurrence: Option<String>,
        kind: T,
        error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
    }

    /// convenience type alias
    pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;

    impl<T: 'static + Display + Debug> ChainError<T> {
        /// Use the `context()` or `map_context()` Result methods instead of calling this directly
        #[inline]
        pub fn new(
            kind: T,
            error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
            occurrence: Option<String>,
        ) -> Self {
            Self {
                occurrence,
                kind,
                error_cause,
            }
        }

        /// return the root cause of the error chain, if any exists
        pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
            self.iter().last()
        }

        /// Find the first error cause of type U, if any exists
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func1Error);
        ///
        /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     func2().context(Func1Error("func1 error".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
        ///         assert!(f1err.find_cause::<io::Error>().is_some());
        ///
        ///         assert!(f1err.find_chain_cause::<Func2Error>().is_some());
        ///     }
        /// #        else {
        /// #            panic!();
        /// #        }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn find_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter().filter_map(Error::downcast_ref::<U>).next()
        }

        /// Find the first error cause of type `ChainError<U>`, if any exists
        ///
        /// Same as `find_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooError);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooError>>();
        ///
        /// // leave out the ChainError<FooError> implementation detail
        /// err.find_chain_cause::<FooError>();
        /// ```
        #[inline]
        pub fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>> {
            self.iter()
                .filter_map(Error::downcast_ref::<ChainError<U>>)
                .next()
        }

        /// Find the first error cause of type `ChainError<U>` or `U`, if any exists and return `U`
        ///
        /// Same as `find_cause` and `find_chain_cause`, but hides the `ChainError<U>` implementation internals
        ///
        /// # Examples
        ///
        /// ```rust
        /// # use chainerror::prelude::v1::*;
        /// # derive_str_context!(FooErrorKind);
        /// # let err = ChainError::new(String::new(), None, None);
        /// // Instead of writing
        /// err.find_cause::<ChainError<FooErrorKind>>();
        /// // and/or
        /// err.find_chain_cause::<FooErrorKind>();
        /// // and/or
        /// err.find_cause::<FooErrorKind>();
        ///
        /// // leave out the ChainError<FooErrorKind> implementation detail
        /// err.find_kind_or_cause::<FooErrorKind>();
        /// ```
        #[inline]
        pub fn find_kind_or_cause<U: Error + 'static>(&self) -> Option<&U> {
            self.iter()
                .filter_map(|e| {
                    e.downcast_ref::<ChainError<U>>()
                        .map(|e| e.kind())
                        .or_else(|| e.downcast_ref::<U>())
                })
                .next()
        }

        /// Return a reference to T of `ChainError<T>`
        ///
        /// # Examples
        ///
        /// ```rust
        /// use chainerror::prelude::v1::*;
        /// use std::error::Error;
        /// use std::io;
        ///
        /// fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     Err(io::Error::from(io::ErrorKind::NotFound))?;
        ///     Ok(())
        /// }
        ///
        /// derive_str_context!(Func2Error);
        ///
        /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
        ///     let filename = "foo.txt";
        ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
        ///     Ok(())
        /// }
        ///
        /// #[derive(Debug)]
        /// enum Func1ErrorKind {
        ///     Func2,
        ///     IO(String),
        /// }
        ///
        /// /// impl ::std::fmt::Display for Func1ErrorKind {…}
        /// # 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),
        /// #         }
        /// #     }
        /// # }
        ///
        /// fn func1() -> ChainResult<(), Func1ErrorKind> {
        ///     func2().context(Func1ErrorKind::Func2)?;
        ///     do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
        ///     Ok(())
        /// }
        ///
        /// if let Err(e) = func1() {
        ///     match e.kind() {
        ///         Func1ErrorKind::Func2 => {}
        ///         Func1ErrorKind::IO(filename) => panic!(),
        ///     }
        /// }
        /// #    else {
        /// #         unreachable!();
        /// #    }
        /// ```
        #[inline]
        pub fn kind(&self) -> &T {
            &self.kind
        }

        /// Returns an Iterator over all error causes/sources
        ///
        /// # Example
        #[inline]
        pub fn iter(&self) -> impl Iterator<Item = &(dyn Error + 'static)> {
            ErrorIter {
                current: Some(self),
            }
        }
    }

    /// Convenience methods for `Result<>` to turn the error into a decorated ChainError
    pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
        /// Decorate the error with a `kind` of type `T` and the source `Location`
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>>;

        /// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>>;
    }

    impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
        for std::result::Result<O, E>
    {
        #[track_caller]
        fn context<T: 'static + Display + Debug>(
            self,
            kind: T,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => Err(ChainError::new(
                    kind,
                    Some(error_cause.into()),
                    Some(Location::caller().to_string()),
                )),
            }
        }

        #[track_caller]
        fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
            self,
            op: F,
        ) -> std::result::Result<O, ChainError<T>> {
            match self {
                Ok(t) => Ok(t),
                Err(error_cause) => {
                    let kind = op(&error_cause);
                    Err(ChainError::new(
                        kind,
                        Some(error_cause.into()),
                        Some(Location::caller().to_string()),
                    ))
                }
            }
        }
    }

    /// An iterator over all error causes/sources
    pub struct ErrorIter<'a> {
        current: Option<&'a (dyn Error + 'static)>,
    }

    impl<'a> Iterator for ErrorIter<'a> {
        type Item = &'a (dyn Error + 'static);

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            let current = self.current;
            self.current = self.current.and_then(Error::source);
            current
        }
    }

    impl<T: 'static + Display + Debug> std::ops::Deref for ChainError<T> {
        type Target = T;

        #[inline]
        fn deref(&self) -> &Self::Target {
            &self.kind
        }
    }

    /// Convenience trait to hide the `ChainError<T>` implementation internals
    pub trait ChainErrorDown {
        /// Test if of type `ChainError<T>`
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool;
        /// Downcast to a reference of `ChainError<T>`
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>;
        /// Downcast to a mutable reference of `ChainError<T>`
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>;
        /// Downcast to T of `ChainError<T>`
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T>;
        /// Downcast to T mutable reference of `ChainError<T>`
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T>;
    }

    impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            TypeId::of::<T>() == TypeId::of::<U>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&*(self as *const dyn Error as *const &ChainError<T>))
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>))
                }
            } else {
                None
            }
        }
        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&(*(self as *const dyn Error as *const &ChainError<T>)).kind)
                }
            } else {
                None
            }
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is_chain::<T>() {
                #[allow(clippy::cast_ptr_alignment)]
                unsafe {
                    #[allow(trivial_casts)]
                    Some(&mut (*(self as *mut dyn Error as *mut &mut ChainError<T>)).kind)
                }
            } else {
                None
            }
        }
    }

    impl ChainErrorDown for dyn Error + 'static {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl ChainErrorDown for dyn Error + 'static + Send + Sync {
        #[inline]
        fn is_chain<T: 'static + Display + Debug>(&self) -> bool {
            self.is::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> {
            self.downcast_ref::<ChainError<T>>()
        }

        #[inline]
        fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> {
            self.downcast_mut::<ChainError<T>>()
        }

        #[inline]
        fn downcast_inner_ref<T: 'static + Error>(&self) -> Option<&T> {
            self.downcast_ref::<T>()
                .or_else(|| self.downcast_ref::<ChainError<T>>().map(|e| e.kind()))
        }

        #[inline]
        fn downcast_inner_mut<T: 'static + Error>(&mut self) -> Option<&mut T> {
            if self.is::<T>() {
                return self.downcast_mut::<T>();
            }

            self.downcast_mut::<ChainError<T>>()
                .and_then(|e| e.downcast_inner_mut::<T>())
        }
    }

    impl<T: 'static + Display + Debug> Error for ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Error for &mut ChainError<T> {
        #[inline]
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            self.error_cause
                .as_ref()
                .map(|e| e.as_ref() as &(dyn Error + 'static))
        }
    }

    impl<T: 'static + Display + Debug> Display for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            write!(f, "{}", self.kind)?;

            #[cfg(feature = "display-cause")]
            {
                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Display::fmt(&e, f)?;
                }
            }
            Ok(())
        }
    }

    impl<T: 'static + Display + Debug> Debug for ChainError<T> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> Result {
            if f.alternate() {
                let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));

                let f = f
                    .field("occurrence", &self.occurrence)
                    .field("kind", &self.kind)
                    .field("source", &self.source());

                f.finish()
            } else {
                if let Some(ref o) = self.occurrence {
                    write!(f, "{}: ", o)?;
                }

                if TypeId::of::<String>() == TypeId::of::<T>()
                    || TypeId::of::<&str>() == TypeId::of::<T>()
                {
                    Display::fmt(&self.kind, f)?;
                } else {
                    Debug::fmt(&self.kind, f)?;
                }

                if let Some(e) = self.source() {
                    writeln!(f, "\nCaused by:")?;
                    Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }
    }

    /// `ChainErrorFrom<T>` is similar to `From<T>`
    pub trait ChainErrorFrom<T>: Sized {
        /// similar to From<T>::from()
        fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
    }

    /// `IntoChainError<T>` is similar to `Into<T>`
    pub trait IntoChainError<T>: Sized {
        /// similar to Into<T>::into()
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
    }

    impl<T, U> IntoChainError<U> for T
    where
        U: ChainErrorFrom<T>,
    {
        #[inline]
        fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
            U::chain_error_from(self, line_filename)
        }
    }

    impl<T, U> ChainErrorFrom<T> for U
    where
        T: Into<U>,
        U: 'static + Display + Debug,
    {
        #[inline]
        fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
            let e: U = t.into();
            ChainError::new(e, None, line_filename)
        }
    }

    /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use crate::chainerror::*;
    /// # use std::error::Error;
    /// # use std::io;
    /// # use std::result::Result;
    /// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
    /// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
    /// #     Ok(())
    /// # }
    /// derive_str_context!(Func2Error);
    ///
    /// fn func2() -> ChainResult<(), Func2Error> {
    ///     let filename = "foo.txt";
    ///     do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
    ///     Ok(())
    /// }
    ///
    /// derive_str_context!(Func1Error);
    ///
    /// fn func1() -> Result<(), Box<dyn Error>> {
    ///     func2().context(Func1Error("func1 error".into()))?;
    ///     Ok(())
    /// }
    /// #     if let Err(e) = func1() {
    /// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
    /// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
    /// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
    /// #         } else {
    /// #             panic!();
    /// #         }
    /// #     } else {
    /// #         unreachable!();
    /// #     }
    /// ```
    #[macro_export]
    macro_rules! derive_str_context {
        ($e:ident) => {
            #[derive(Clone)]
            pub struct $e(pub String);
            impl ::std::fmt::Display for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}", self.0)
                }
            }
            impl ::std::fmt::Debug for $e {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                    write!(f, "{}({})", stringify!($e), self.0)
                }
            }
            impl ::std::error::Error for $e {}
        };
    }

    /// Derive an Error for an ErrorKind, which wraps a `ChainError` and implements a `kind()` method
    ///
    /// It basically hides `ChainError` to the outside and only exposes the `kind()`
    /// method.
    ///
    /// Error::kind() returns the ErrorKind
    /// Error::source() returns the parent error
    ///
    /// # Examples
    ///
    /// ```rust
    /// use chainerror::prelude::v1::*;
    /// use std::io;
    ///
    /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
    ///     return Err(io::Error::from(io::ErrorKind::NotFound));
    /// }
    ///
    /// #[derive(Debug, Clone)]
    /// pub enum ErrorKind {
    ///     IO(String),
    ///     FatalError(String),
    ///     Unknown,
    /// }
    ///
    /// derive_err_kind!(Error, ErrorKind);
    ///
    /// impl std::fmt::Display for ErrorKind {
    ///     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
    ///         match self {
    ///             ErrorKind::FatalError(e) => write!(f, "fatal error {}", e),
    ///             ErrorKind::Unknown => write!(f, "unknown error"),
    ///             ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename),
    ///         }
    ///     }
    /// }
    ///
    /// impl ErrorKind {
    ///     fn from_io_error(e: &io::Error, f: String) -> Self {
    ///         match e.kind() {
    ///             io::ErrorKind::BrokenPipe => panic!("Should not happen"),
    ///             io::ErrorKind::ConnectionReset => {
    ///                 ErrorKind::FatalError(format!("While reading `{}`: {}", f, e))
    ///             }
    ///             _ => ErrorKind::IO(f),
    ///         }
    ///     }
    /// }
    ///
    /// impl From<&io::Error> for ErrorKind {
    ///     fn from(e: &io::Error) -> Self {
    ///         ErrorKind::IO(format!("{}", e))
    ///     }
    /// }
    ///
    /// pub fn func1() -> std::result::Result<(), Error> {
    ///     let filename = "bar.txt";
    ///
    ///     do_some_io(filename).map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
    ///     do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
    ///     Ok(())
    /// }
    /// ```
    #[macro_export]
    macro_rules! derive_err_kind {
        ($e:ident, $k:ident) => {
            pub struct $e($crate::ChainError<$k>);

            impl $e {
                pub fn kind(&self) -> &$k {
                    self.0.kind()
                }
            }

            impl From<$k> for $e {
                fn from(e: $k) -> Self {
                    $e($crate::ChainError::new(e, None, None))
                }
            }

            impl From<ChainError<$k>> for $e {
                fn from(e: $crate::ChainError<$k>) -> Self {
                    $e(e)
                }
            }

            impl From<&$e> for $k
            where
                $k: Clone,
            {
                fn from(e: &$e) -> Self {
                    e.kind().clone()
                }
            }

            impl std::error::Error for $e {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.0.source()
                }
            }

            impl std::fmt::Display for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for $e {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Debug::fmt(&self.0, f)
                }
            }
        };
    }
    }
    pub mod mycrate {
        use crate::chainerror::*; // omit the `crate::` part
        use std::io;

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

        derive_str_context!(Func2Error);

        fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
            let filename = "foo.txt";
            do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
            Ok(())
        }

        #[derive(Debug, Clone)]
        pub enum ErrorKind {
            Func2,
            IO(String),
        }

        derive_err_kind!(Error, ErrorKind);

        pub type Result<T> = std::result::Result<T, Error>;

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

        pub fn func1() -> Result<()> {
            func2().context(ErrorKind::Func2)?;
            let filename = String::from("bar.txt");
            do_some_io().context(ErrorKind::IO(filename))?;
            Ok(())
        }
    }

    fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        use mycrate::func1;
        use mycrate::ErrorKind;
        use std::error::Error;
        use std::io;

        if let Err(e) = func1() {
            match e.kind() {
                ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
                ErrorKind::IO(ref filename) => {
                    eprintln!("Main Error Report: func1 error reading '{}'", filename)
                }
            }

            eprintln!();
            let mut s: &dyn Error = &e;
            while let Some(c) = s.source() {
                if let Some(ioerror) = c.downcast_ref::<io::Error>() {
                    eprintln!("caused by: std::io::Error: {}", ioerror);
                    match ioerror.kind() {
                        io::ErrorKind::NotFound => eprintln!("of kind: std::io::ErrorKind::NotFound"),
                        _ => {}
                    }
                } else {
                    eprintln!("caused by: {}", c);
                }
                s = c;
            }

            eprintln!("\nDebug Error:\n{:?}", e);

            std::process::exit(1);
        }
        Ok(())
    }

# Going back to std

Not using `chainerror` and going full `std` would look like this:

Btw, the code size is bigger than using `chainerror` :-)

    pub mod mycrate {
        use std::error::Error as StdError;

        use self::func2mod::{do_some_io, func2};

        pub mod func2mod {
            use std::error::Error as StdError;
            use std::io;

            pub enum ErrorKind {
                IO(String),
            }

            impl std::fmt::Display for ErrorKind {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
                    match self {
                        ErrorKind::IO(s) => std::fmt::Display::fmt(s, f),
                    }
                }
            }

            impl std::fmt::Debug for ErrorKind {
                fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::fmt::Result {
                    match self {
                        ErrorKind::IO(s) => std::fmt::Display::fmt(s, f),
                    }
                }
            }

            macro_rules! mcontext {
                ( $k:expr ) => {{
                    |e| {
                        Error(
                            $k,
                            Some(Box::from(e)),
                            Some(concat!(file!(), ":", line!(), ": ")),
                        )
                    }
                }};
            }

            pub struct Error(
                ErrorKind,
                Option<Box<dyn std::error::Error + 'static>>,
                Option<&'static str>,
            );

            impl Error {
                pub fn kind(&self) -> &ErrorKind {
                    &self.0
                }
            }

            impl From<ErrorKind> for Error {
                fn from(e: ErrorKind) -> Self {
                    Error(e, None, None)
                }
            }

            impl std::error::Error for Error {
                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                    self.1.as_ref().map(|e| e.as_ref())
                }
            }

            impl std::fmt::Display for Error {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    std::fmt::Display::fmt(&self.0, f)
                }
            }

            impl std::fmt::Debug for Error {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    if let Some(ref o) = self.2 {
                        std::fmt::Display::fmt(o, f)?;
                    }

                    std::fmt::Debug::fmt(&self.0, f)?;

                    if let Some(e) = self.source() {
                        std::fmt::Display::fmt("\nCaused by:\n", f)?;
                        std::fmt::Debug::fmt(&e, f)?;
                    }
                    Ok(())
                }
            }

            pub fn do_some_io() -> std::result::Result<(), Box<dyn std::error::Error>> {
                Err(io::Error::from(io::ErrorKind::NotFound))?;
                Ok(())
            }

            pub fn func2() -> std::result::Result<(), Error> {
                let filename = "foo.txt";
                do_some_io().map_err(mcontext!(ErrorKind::IO(format!(
                    "Error reading '{}'",
                    filename
                ))))?;
                Ok(())
            }
        }

        #[derive(Debug)]
        pub enum ErrorKind {
            Func2,
            IO(String),
        }

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

        macro_rules! mcontext {
            ( $k:expr ) => {{
                |e| {
                    Error(
                        $k,
                        Some(Box::from(e)),
                        Some(concat!(file!(), ":", line!(), ": ")),
                    )
                }
            }};
        }

        pub struct Error(
            ErrorKind,
            Option<Box<dyn std::error::Error + 'static>>,
            Option<&'static str>,
        );

        impl Error {
            pub fn kind(&self) -> &ErrorKind {
                &self.0
            }
        }

        impl From<ErrorKind> for Error {
            fn from(e: ErrorKind) -> Self {
                Error(e, None, None)
            }
        }

        impl std::error::Error for Error {
            fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                self.1.as_ref().map(|e| e.as_ref())
            }
        }

        impl std::fmt::Display for Error {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                std::fmt::Display::fmt(&self.0, f)
            }
        }

        impl std::fmt::Debug for Error {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                if let Some(ref o) = self.2 {
                    std::fmt::Display::fmt(o, f)?;
                }

                std::fmt::Debug::fmt(&self.0, f)?;
                if let Some(e) = self.source() {
                    std::fmt::Display::fmt("\nCaused by:\n", f)?;
                    std::fmt::Debug::fmt(&e, f)?;
                }
                Ok(())
            }
        }

        pub type Result<T> = std::result::Result<T, Error>;

        pub fn func1() -> Result<()> {
            func2().map_err(mcontext!(ErrorKind::Func2))?;
            let filename = String::from("bar.txt");
            do_some_io().map_err(mcontext!(ErrorKind::IO(filename)))?;
            Ok(())
        }
    }

    fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        use mycrate::func1;
        use mycrate::ErrorKind;
        use std::error::Error;
        use std::io;

        if let Err(e) = func1() {
            match e.kind() {
                ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
                ErrorKind::IO(ref filename) => {
                    eprintln!("Main Error Report: func1 error reading '{}'", filename)
                }
            }

            eprintln!();
            let mut s: &dyn Error = &e;
            while let Some(c) = s.source() {
                if let Some(ioerror) = c.downcast_ref::<io::Error>() {
                    eprintln!("caused by: std::io::Error: {}", ioerror);
                    match ioerror.kind() {
                        io::ErrorKind::NotFound => eprintln!("of kind: std::io::ErrorKind::NotFound"),
                        _ => {}
                    }
                } else {
                    eprintln!("caused by: {}", c);
                }
                s = c;
            }

            eprintln!("\nDebug Error:\n{:?}", e);

            std::process::exit(1);
        }
        Ok(())
    }

# The End

That's it for now…

Happy error handling!

To report issues, submit pull request or for the source code, examples and the book source, visit the Git Repo.