snafu 0.4.4

An ergonomic error handling library
Documentation
# Details about the output of the `Snafu` macro

This procedural macro:

- produces the corresponding context selectors
- implements the [`Error`][Error] trait
- implements the [`Display`][Display] trait
- implements the [`ErrorCompat`][ErrorCompat] trait

## Detailed example

```rust
use snafu::{Backtrace, Snafu};
use std::path::PathBuf;

#[derive(Debug, Snafu)]
enum Error {
    #[snafu(display("Could not open config at {}: {}", filename.display(), source))]
    OpenConfig {
        filename: PathBuf,
        source: std::io::Error,
    },
    #[snafu(display("Could not open config: {}", "source"))]
    SaveConfig { source: std::io::Error },
    #[snafu(display("The user id {} is invalid", user_id))]
    UserIdInvalid { user_id: i32, backtrace: Backtrace },
}
```

### Generated code

<div style="background: #ffffd0; padding: 0.6em; margin-bottom: 0.6em;">

**Note** — The actual generated code may differ in exact names and
details. This section is only intended to provide general
guidance.

</div>

#### Context selectors

This will generate three additional types called *context
selectors*:

```rust,ignore
struct OpenConfig<P> { filename: P }
struct SaveConfig<P>;
struct UserIdInvalid<I> { user_id: I }
```

Notably:

1. One context selector is created for each enum variant.
1. The name of the selector is the same as the enum variant's name.
1. The `source` and `backtrace` fields have been removed; the
   library will automatically handle this for you.
1. Each remaining field's type has been replaced with a generic
   type.
1. If there are no fields remaining for the user to specify, the
   selector will not require curly braces.

If the original variant had a `source` field, its context selector
will have an implementation of [`IntoError`][IntoError]:

```rust,ignore
impl<P> IntoError<Error> for OpenConfig<P>
where
    P: Into<PathBuf>,
```

Otherwise, the context selector will have an inherent method
`fail` and can be used with the [`ensure`](ensure) macro:

```rust,ignore
impl<I> UserIdInvalid<I>
where
    I: Into<i32>,
{
    fn fail<T>(self) -> Result<T, Error> { /* ... */ }
}
```

If the original variant had a `backtrace` field, the backtrace
will be automatically constructed when either `IntoError` or
`fail` are called.

#### `Error`

[`Error::source`][source] will return the underlying error, if
there is one:

```rust,ignore
impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            Error::OpenConfig { source, .. } => Some(source),
            Error::SaveConfig { source, .. } => Some(source),
            Error::UserIdInvalid { .. } => None,
        }
    }
}
```

[`Error::cause`][cause] will return the same as `source`. As
[`Error::description`][description] is soft-deprecated, it will
return a string matching the name of the variant.

#### `Display`

Every field of the enum variant is made available to the format
string, even if they are not used:

```rust,ignore
impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter ) -> fmt::Result {
        match self {
            Error::OpenConfig { filename, source } =>
                write!(f, "Could not open config at {}: {}", filename.display(), source),
            Error::SaveConfig { source } =>
                write!(f, "Could not open config: {}", source),
            Error::UserIdInvalid { user_id, backtrace } =>
                write!(f, "The user id {} is invalid", user_id),
        }
    }
}
```

If no display format is specified, the variant's name will be used
by default. If the field is an underlying error, that error's
`Display` implementation will also be included.

#### `ErrorCompat`

Every variant that carries a backtrace will return a reference to
that backtrace.

```rust,ignore
impl snafu::ErrorCompat for Error {
    fn backtrace(&self) -> Option<&Backtrace> {
        match self {
            Error::OpenConfig { .. } => None,
            Error::SaveConfig { .. } => None,
            Error::UserIdInvalid { backtrace, .. } => Some(backtrace),
        }
    }
}
```

[Display]: std::fmt::Display
[ErrorCompat]: crate::ErrorCompat
[Error]: std::error::Error
[IntoError]: crate::IntoError
[cause]: std::error::Error::cause
[description]: std::error::Error::description
[source]: std::error::Error::source