#[derive(Error2)]
{
// Attributes available to this derive:
#[error2]
}
derive only.Expand description
Derives the Error2 trait for an error type.
This macro automatically implements:
std::error::Errorerror2::Error2Display(only if#[error2(display(...))]is specified)
It also generates helper structs (named {Type}2 or {Variant}2) for type conversion.
§Attributes
§Type-Level Attributes
Applied to the struct or enum definition:
§display
Specifies the display format for the error message. Only applicable to structs.
If omitted, no Display implementation is generated, allowing custom implementation.
#[derive(Debug, Error2)]
#[error2(display("Failed to process: {item}"))]
struct ProcessError {
item: String,
backtrace: Backtrace,
}§vis
Controls the visibility of generated helper structs and their fields. Default is inherited from the error type.
#[derive(Debug, Error2)]
#[error2(vis(pub(crate)), display("error: {code}"))]
pub struct MyError {
code: i32,
backtrace: Backtrace,
}
// Generates:
// pub(crate) struct MyError2<T: Into<i32>> {
// pub(crate) code: T
// }§module
Puts generated code into a submodule with the same name as the type (in snake_case).
#[derive(Debug, Error2)]
#[error2(module, display("my error"))]
pub struct MyError {
backtrace: Backtrace,
}
#[derive(Debug, Error2)]
#[error2(module, display("read config error"))]
pub struct ReadConfigError {
backtrace: Backtrace,
}
// Generates:
// mod my_error { pub(super) struct MyError2; }
// mod read_config_error { pub(super) struct ReadConfigError2; }
// Usage - helper structs are in their respective modules:
my_error::MyError2.fail()?;
read_config_error::ReadConfigError2.fail()?;§Variant-Level Attributes
Applied to enum variants:
§display
Specifies the display format for this variant. If omitted, no Display
implementation is generated for this variant.
#[derive(Debug, Error2)]
pub enum AppError {
#[error2(display("IO error at {path}"))]
Io {
path: String,
source: std::io::Error,
backtrace: Backtrace,
},
#[error2(display("Not found: {item}"))]
NotFound { item: String, backtrace: Backtrace },
}§Generated Helper Structs
The macro generates helper structs for type conversion, named by appending 2:
For structs:
#[derive(Debug, Error2)]
#[error2(display("my error"))]
struct MyError {
backtrace: Backtrace,
}
// Generates: struct MyError2;For enum variants:
#[derive(Debug, Error2)]
enum AppError {
#[error2(display("file error"))]
FileError {
source: std::io::Error,
backtrace: Backtrace,
},
}
// Generates: struct FileError2;These helper structs contain only the non-source and non-backtrace fields.
All fields are generic with Into trait bounds, allowing automatic type conversion:
#[derive(Debug, Error2)]
#[error2(display("read error: {path}"))]
struct ReadError {
path: String,
source: std::io::Error,
backtrace: Backtrace,
}
// Generates (assuming ReadError has inherited visibility):
// struct ReadError2<T: Into<String>> { path: T }
// No need to call .into() - automatic conversion:
std::fs::read_to_string("file.txt").context(ReadError2 { path: "file.txt" })?; // &str -> String
//For expensive conversions, use .with_context() for lazy evaluation:
// Only converts on error:
std::fs::read(path).with_context(|| ReadError2 {
path: path.display().to_string(),
})?;§Boxing Large Source Errors
To avoid large Result<T, E> types, you can wrap the source error in a Box or other wrapper:
use std::io;
#[derive(Debug, Error2)]
#[error2(display("IO error: {path}"))]
struct IoError {
path: String,
// Box the source to keep Result size small
source: Box<io::Error>,
backtrace: Backtrace,
}
// io::Error is automatically boxed via Into trait
std::fs::read_to_string(path).context(IoError2 { path })?;This works because the helper struct implements Into<Box<E>> for E.
Any wrapper type that implements E: Into<Wrapper<E>> can be used.
§Display Implementation
Important: The Display trait is only implemented when display attribute is present.
This allows you to provide custom Display implementations:
use std::fmt;
#[derive(Debug, Error2)]
struct MyError {
code: i32,
backtrace: Backtrace,
}
// Custom Display implementation (no display attribute needed)
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Error code: {:#x}", self.code)
}
}