Crate derive_error_chain [−] [src]
A Macros 1.1 implementation of https://crates.io/crates/error-chain
The error-chain example
mod other_error { error_chain! {} } error_chain! { types { Error, ErrorKind, ResultExt, Result; } links { Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)]; } foreign_links { Fmt(::std::fmt::Error); Io(::std::io::Error) #[cfg(unix)]; } errors { InvalidToolchainName(t: String) { description("invalid toolchain name") display("invalid toolchain name: '{}'", t) } } }
becomes
mod other_error { #[derive(Debug, error_chain)] pub enum ErrorKind { Msg(String), } } #[derive(Debug, error_chain)] pub enum ErrorKind { Msg(String), #[cfg(unix)] #[error_chain(link = "other_error::Error")] Another(other_error::ErrorKind), #[error_chain(foreign)] Fmt(::std::fmt::Error), #[cfg(unix)] #[error_chain(foreign)] Io(::std::io::Error), #[error_chain(custom)] #[error_chain(description = r#"|_| "invalid toolchain name""#)] #[error_chain(display = r#"|t| write!(f, "invalid toolchain name: '{}'", t)"#)] InvalidToolchainName(String), }
So the obvious differences from error_chain!
are:
- The ErrorKind is an enum instead of a macro invocation.
- Error links are variants of the enum instead of lines inside the macro.
- Links have explicit annotations marking them as chainable / foreign / custom instead of being grouped into corresponding sections of the macro.
- Attributes like
#[cfg]
are applied to the variants directly instead of needing special syntax. description
anddisplay
are defined as function expressions specified as attribute values, instead of shorthands integrated into the macro syntax.
The less obvious differences are:
- The ErrorKind must explicitly implement
::std::fmt::Debug
, either automatically using#[derive]
or manually implemented separately.error_chain!
does this implicitly. - The ErrorKind must have
pub
visibility.error_chain!
does this implicitly. - The ErrorKind must have a special
Msg(String)
member.error_chain!
does this implicitly. - Doc comments, since they're effectively attributes, can be applied on the enum variants without any special syntax like
error_chain!
has. - The ErrorKind can be generic.
Enum attributes
#[error_chain(error = "ErrorName")]
Override the name of the generated
Error
struct to the given name. If not provided, the struct will be namedError
.#[error_chain(result_ext = "ResultExtName")]
Override the name of the generated
ResultExt
trait to the given name. If not provided, the trait will be namedResultExt
.#[error_chain(result = "ResultName")]
Override the name of the generated
Result
type alias to the given name. If not provided, the alias will be namedResult
. If set to the empty string""
, the alias will not be generated at all.#[error_chain(backtrace = "false")]
or#[error_chain(backtrace = false)]
Disable backtrace functionality in the generated code. This should be kept in sync with the value of the
backtrace
feature of theerror-chain
crate. In other words, if you setbacktrace = "false"
here, you must also specifydefault-features = false
forerror-chain
in yourCargo.toml
Variant definitions
Chainable links
#[error_chain(link = "other_error::Error")] Another(other_error::ErrorKind),
A chainable link is an error and errorkind that have been generated using
error-chain
orderive-error-chain
. The variant must have a single field to hold the chained errorkind, and thelink
attribute must specify a path to the chained error.Foreign links
#[error_chain(foreign)] Fmt(::std::fmt::Error),
A foreign link is an error that implements
::std::error::Error
but otherwise does not followerror-chain
's conventions. The variant must have a single field to hold the foreign error.Custom links
#[error_chain(custom)] InvalidToolchainName(String),
A custom link is an arbitrary variant that can hold any members.
Variant attributes
In addition to the above attributes that identify the type of the variant's link, the below attributes can be used on all links.
#[error_chain(description = "some_function_expression")]
Specifies a function expression to be used to implement
ErrorKind::description()
. This value is also returned from the implementation of::std::error::Error::description()
on the generatedError
.This can be an inline lambda:
#[error_chain(description = r#"|_| "invalid toolchain name""#)] InvalidToolchainName(String),
or it can be a separate function:
#[error_chain(description = "invalid_toolchain_name_error_description")] InvalidToolchainName(String), // <snip> fn invalid_toolchain_name_error_description(_: &str) -> &str { "invalid toolchain name" }
The function expression must have the signature
(...) -> &'static str
. It should have one parameter for each field of the variant. The fields are passed in by reference.Thus in the above example, since
InvalidToolchainName
had a single field of typeString
, the function expression needed to be of type(&str) -> &'static str
If not specified, the default implementation behaves in this way:
- Chainable links: Forwards to the chained error kind's
description()
- Foreign links: Forwards to the foreign error's implementation of
::std::error::Error::description()
- Custom links: Returns the stringified name of the variant.
- Chainable links: Forwards to the chained error kind's
#[error_chain(display = "some_function_expression")]
Specifies a function expression to be used to implement
::std::fmt::Display::fmt()
on theErrorKind
and generatedError
This can be an inline lambda:
#[error_chain(display = r#"|t| write!(f, "invalid toolchain name: '{}'", t)"#)] InvalidToolchainName(String),
or it can be a separate function:
#[error_chain(display = "invalid_toolchain_name_error_display")] InvalidToolchainName(String), // <snip> fn invalid_toolchain_name_error_display(f: &mut ::std::fmt::Formatter, t: &str) -> ::std::fmt::Result { write!(f, "invalid toolchain name: '{}'", t) }
The function expression must have the signature
(&mut ::std::fmt::Formatter, ...) -> ::std::fmt::Result
. It should have one&mut ::std::fmt::Formatter
parameter, and one parameter for each field of the variant. The fields are passed in by reference. For brevity, closure expressions do not need the&mut ::std::fmt::Formatter
parameter and instead capturef
from the closure environment.Thus in the above example, since
InvalidToolchainName
had a single field of typeString
, the function expression needed to be of type(&mut ::std::fmt::Formatter, &str) -> ::std::fmt::Result
If not specified, the default implementation of
::std::fmt::Display::fmt()
behaves in this way:- Chainable links: Forwards to the chained errorkind's implementation of
::std::fmt::Display::fmt()
- Foreign links: Forwards to the foreign error's implementation of
::std::fmt::Display::fmt()
- Custom links: Writes the description of the variant to the formatter.
- Chainable links: Forwards to the chained errorkind's implementation of
#[error_chain(cause = "some_function_expression")]
Specifies a function expression to be used to implement
::std::fmt::Error::cause()
on the generatedError
This can be an inline lambda:
#[error_chain(cause = "|_, err| err")] JSON(::std::path::PathBuf, ::serde_json::Error),
or it can be a separate function:
#[error_chain(cause = "parse_json_file_error_cause")] JSON(::std::path::PathBuf, ::serde_json::Error), // <snip> fn parse_json_file_error_cause<'a>(_: &::std::path::Path, err: &'a ::serde_json::Error) -> &'a ::std::error::Error { err }
The function expression must have the signature
(...) -> &::std::error::Error
. It should have one parameter for each field of the variant. The fields are passed in by reference. The result is wrapped inOption::Some()
for returning from::std::error::Error::cause()
Thus in the above example, since
JSON
had two fields of type::std::path::PathBuf
and::serde_json::Error
, the function expression needed to be of type(&::std::path::Path, &::serde_json::Error) -> &::std::error::Error
If not specified, the default implementation of
::std::error::Error::cause()
behaves in this way:- Chainable links: Returns
None
- Foreign links: Forwards to the foreign error's implementation of
::std::error::Error::cause()
- Custom links: Returns
None
- Chainable links: Returns
Notes
If you want to use other macros from the error_chain
like bail!
, note that the following code:
#[macro_use] extern crate derive_error_chain; #[macro_use] extern crate error_chain; #[derive(Debug, error_chain)] enum ErrorKind { Msg(String), }
will fail to compile with:
error: macro `error_chain` may not be used for derive attributes
This is because both crates export a macro named error_chain
and the macro from the second crate overrides the first.
To fix this, import error_chain
before derive_error_chain
:
#[macro_use] extern crate error_chain; #[macro_use] extern crate derive_error_chain;
or use a fully-qualified path for the custom derive (nightly only):
#![feature(proc_macro)] extern crate derive_error_chain; #[macro_use] extern crate error_chain; #[derive(Debug, derive_error_chain::error_chain)] enum ErrorKind { Msg(String), }
Functions
derive_error_chain |