Derive Macro Box
#[derive(Box)]
{
// Attributes available to this derive:
#[thiserror_ext]
}
Expand description
Generates a new type that wraps the original error type in a [struct@Box
].
Specify the name of the new type with #[thiserror_ext(newtype(name = ..))]
.
§Reduce size
The most common motivation for using this macro is to reduce the size of
the original error type. As a sum-type, a [Result
] is at least as large
as its largest variant. Large error type may hurt the performance of a
function call returning a [Result
]. With this macro, the new type always
has the same size as a [struct@Box
].
On the other hand, returning an error should be an exceptional case in most cases. Therefore, even though boxing the error type may lead to extra allocation, it’s usually acceptable.
§Example
#[derive(Debug, thiserror::Error, thiserror_ext::Box)]
#[thiserror_ext(newtype(name = Error))]
enum ErrorKind {
#[error("foo")]
Foo,
#[error("io")]
Io(#[from] std::io::Error),
}
// The size of `Error` is one pointer.
assert_eq!(std::mem::size_of::<Error>(), std::mem::size_of::<usize>());
// Convert to `Error`, from `ErrorKind` or other types that can be converted
// to `ErrorKind`.
let error: Error = ErrorKind::Foo.into();
let error: Error = io_error().into();
// Get the reference or the value of the inner error.
let _: &ErrorKind = error.inner();
let _: ErrorKind = error.into_inner();
§Backtrace
Another use case is to capture backtrace when the error is created. Without
a new type, one has to manually add a Backtrace
field to each variant
of the error type. The new type allows one to capture backtrace in a single
place.
Specify #[thiserror_ext(newtype(.., backtrace))]
to enable capturing
backtrace. The extra backtrace is captured only if the original error
type does not provide
one. Typically, this should be maintained by the
#[backtrace]
attribute from thiserror
.
§Example
#[derive(Debug, thiserror::Error, thiserror_ext::Box)]
#[thiserror_ext(newtype(name = Error, backtrace))]
enum ErrorKind {
#[error("foo")]
Foo,
}
let error: Error = ErrorKind::Foo.into();
let backtrace: &Backtrace = std::error::request_ref(&error).unwrap();