Expand description
§err-derive
§Deriving error causes / sources
Add an #[error(source)]
attribute to the field:
use std::io;
use err_derive::Error;
/// `MyError::source` will return a reference to the `io_error` field
#[derive(Debug, Error)]
#[error(display = "An error occurred.")]
struct MyError {
#[error(source)]
io_error: io::Error,
}
§Automatic From implementations
From#[source]
attribute.
In cases where multiple enum variants have a #[source]
field of the same type
all but one of the variants need to be opted-out from the automatic From implementation (see
below).
use std::io;
use err_derive::Error;
/// `From<io::Error>` will be implemented for `MyError`
#[derive(Debug, Error)]
#[error(display = "An error occurred.")]
struct MyError {
#[error(from)]
io_error: io::Error,
}
§Opt out of From implementation
Use the #[no_from]
attribute on either the enum or a single variant to opt-out of the
automatic From implementation.
When #[no_from]
is set on the enum, you can opt-in individual variants by using #[from]
use err_derive::Error;
use std::{io, fmt};
#[derive(Debug, Error)]
enum ClientError {
#[error(display = "regular bad io error {}", _0)]
Io(#[source] io::Error),
#[error(display = "extra bad io error {}", _0)]
// Without #[no_from], this From impl would conflict with the normal Io error
ReallyBadIo(#[error(source, no_from)] io::Error)
}
#[derive(Debug, Error)]
#[error(no_from)] // Don't impl From for any variants by default
enum InnerError {
#[error(display = "an error")]
Io(#[source] io::Error),
#[error(display = "an error")]
// Opt-in impl From for a single variant
Formatting(#[error(source, from)] fmt::Error)
}
§Auto-boxing From implementation
If an enum single variant has Box<T>
as its type, a From
implementation for T
will be automatically be generated that wraps it in
Box::new
.
use err_derive::Error;
use std::{io, fmt};
#[derive(Debug, Error)]
enum ClientError {
#[error(display = "io error in a box{}", _0)]
Io(#[error(source)] Box<io::Error>),
}
§Formatting fields
use std::path::PathBuf;
use err_derive::Error;
#[derive(Debug, Error)]
pub enum FormatError {
#[error(display = "invalid header (expected: {:?}, got: {:?})", expected, found)]
InvalidHeader {
expected: String,
found: String,
},
// Note that tuple fields need to be prefixed with `_`
#[error(display = "missing attribute: {:?}", _0)]
MissingAttribute(String),
}
#[derive(Debug, Error)]
pub enum LoadingError {
#[error(display = "could not decode file")]
FormatError(#[error(source)] #[error(from)] FormatError),
#[error(display = "could not find file: {:?}", path)]
NotFound { path: PathBuf },
}
§Printing the error
use std::error::Error;
fn print_error(e: &dyn Error) {
eprintln!("error: {}", e);
let mut cause = e.source();
while let Some(e) = cause {
eprintln!("caused by: {}", e);
cause = e.source();
}
}