14个版本
使用旧Rust 2015
0.11.2 | 2018年5月23日 |
---|---|
0.11.0 | 2017年9月7日 |
0.10.1 | 2017年5月14日 |
0.10.0 | 2017年2月26日 |
0.1.2 | 2016年11月18日 |
#21 在 #error-chain
11,883 每月下载量
在 46 个crate中使用 (4 直接)
61KB
878 行
https://crates.io/crates/error-chain 的宏实现
error-chain示例
#
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)
}
}
}
变为
#
mod other_error {
#[derive(Debug, ErrorChain)]
pub enum ErrorKind {
Msg(String),
}
}
#[derive(Debug, ErrorChain)]
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),
}
与error_chain!
相比的明显差异是
ErrorKind
是一个枚举而不是宏调用。- 错误链接是枚举的变体而不是宏内部的行。
- 链接有显式的注解标记它们为链式/外部/自定义,而不是被分组到宏的相应部分。
- 如
#[cfg]
之类的属性直接应用于变体,而不是需要特殊的语法。 description
和display
被定义为作为属性值指定的函数表达式,而不是集成到宏语法中的缩写。
不那么明显的差异是
ErrorKind
必须显式实现::std::fmt::Debug
,要么自动使用#[derive]
或手动单独实现。error_chain!
隐式地这样做。- 与
error_chain!
不同,ErrorKind
不需要有pub
可见性。生成的Error
、Result
和ResultExt
将与ErrorKind
具有相同的可见性。 ErrorKind
可以有一个特殊的Msg(String)
成员,用于将字符串转换为ErrorKind
。error_chain!
隐式地执行此操作。- 与
error-chain
不同,Msg(String)
成员是可选的。如果不存在,则ErrorKind
和Error
不会实现From<String>
和From<&str>
。 - 文档注释,由于它们实际上相当于属性,可以应用于枚举变体,而无需像
error_chain!
那样的特殊语法。 ErrorKind
可以是泛型的。
枚举属性
-
#[error_chain(error= "ErrorName")]
将生成的
Error
结构体的名称重写为给定的名称。如果没有提供,结构体的名称将为Error
。 -
#[error_chain(result_ext= "ResultExtName")]
将生成的
ResultExt
特质的名称重写为给定的名称。如果没有提供,特质的名称将为ResultExt
。 -
#[error_chain(result= "ResultName")]
将生成的
Result
类型别名的名称重写为给定的名称。如果没有提供,别名将命名为Result
。如果设置为空字符串""
,则不会生成该别名。 -
#[error_chain(backtrace = "false")]
或#[error_chain(backtrace = false)]
在生成的代码中禁用回溯功能。这应与
error-chain
crate中backtrace
功能的值保持一致。换句话说,如果您在这里将backtrace = "false"
设置,则还必须在您的Cargo.toml
中指定default-features = false
。
变体定义
-
可链接的链接
# # #[error_chain(link = "other_error::Error")] Another(other_error::ErrorKind),
可链接的链接是使用
error-chain
或derive-error-chain
生成的错误和errorkind。变体必须有一个字段来保存链式errorkind,并且link
属性必须指定链式错误的路径。当启用
proc_macro
功能时,link
属性的值不需要进行字符串化。# # # #[error_chain(link = other_error::Error)] Another(other_error::ErrorKind),
-
外部链接
# #[error_chain(foreign)] Fmt(::std::fmt::Error),
外部链接是一种错误,它实现了
::std::error::Error
,但其他方面不遵循error-chain
的约定。变体必须有一个字段来存储外部错误。 -
自定义链接
# #[error_chain(custom)] InvalidToolchainName(String),
自定义链接是一个任意变体,可以持有任何成员。
变体属性
除了上述标识变体链接类型的属性外,以下属性可以用于所有链接。
-
#[error_chain(描述= "some_function_expression")]
指定一个函数表达式,用于实现
ErrorKind::description()
。此值也返回自生成的Error
上::std::error::Error::description()
的实现。这可以是一个内联lambda
# # #[error_chain(custom)] #[error_chain(description = r#"|_| "invalid toolchain name""#)] InvalidToolchainName(String),
或者它可以是单独的函数
# # #[error_chain(custom)] #[error_chain(description = "invalid_toolchain_name_error_description")] InvalidToolchainName(String), // <snip> fn invalid_toolchain_name_error_description(_: &str) -> &str { "invalid toolchain name" }
函数表达式必须具有签名
(...) -> &'static str
。它应该有一个参数对应于变体的每个字段。字段通过引用传递。因此,在上面的例子中,由于
InvalidToolchainName
只有一个类型为String
的字段,函数表达式需要是类型(&str) -> &'static str
如果没有指定,默认实现的行为是这样的
- 链式链接:转发到链式错误类型的
description()
- 外部链接:转发到外部错误的
::std::error::Error::description()
实现 - 自定义链接:返回变体的字符串化名称。
当启用
proc_macro
功能时,不需要将值字符串化# # # #[error_chain(custom)] #[error_chain(description = |_| "invalid toolchain name")] InvalidToolchainName(String),
# # # #[error_chain(custom)] #[error_chain(description = invalid_toolchain_name_error_description)] InvalidToolchainName(String), #
当启用
proc_macro
功能时,仅调用write!
的闭包表达式可以替代简写# # # #[error_chain(custom)] #[error_chain(description = const("invalid toolchain name"))] InvalidToolchainName(String),
- 链式链接:转发到链式错误类型的
-
#[error_chain(显示= "some_function_expression")]
指定一个函数表达式,用于在
ErrorKind
和生成的Error
上实现::std::fmt::Display::fmt()
这可以是一个内联lambda
# # #[error_chain(custom)] #[error_chain(display = r#"|t| write!(f, "invalid toolchain name: '{}'", t)"#)] InvalidToolchainName(String),
或者它可以是单独的函数
# # #[error_chain(custom)] #[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) }
函数表达式必须具有以下签名:
(&mut ::std::fmt::Formatter, ...) -> ::std::fmt::Result
。它应该有一个&mut ::std::fmt::Formatter
参数,以及一个参数对应变体的每个字段。字段通过引用传递。为了简洁,闭包表达式不需要&mut ::std::fmt::Formatter
参数,而是从闭包环境中捕获f
。因此,在上面的例子中,由于
InvalidToolchainName
只有一个类型为String
的字段,函数表达式必须具有类型(&mut ::std::fmt::Formatter, &str) -> ::std::fmt::Result
如果没有指定,默认的
::std::fmt::Display::fmt()
实现将以这种方式行为- 链式链接:转发到链式 errorkind 的
::std::fmt::Display::fmt()
实现中 - 外部链接:转发到外部错误的
::std::fmt::Display::fmt()
实现中 - 自定义链接:将变体的描述写入格式化器。
当启用
proc_macro
功能时,不需要将值字符串化# # # #[error_chain(custom)] #[error_chain(display = |t| write!(f, "invalid toolchain name: '{}'", t))] InvalidToolchainName(String),
# # # #[error_chain(custom)] #[error_chain(display = invalid_toolchain_name_error_display)] InvalidToolchainName(String), #
当启用
proc_macro
功能时,仅调用write!
的闭包表达式可以替代简写# # // Tuple variants use `{0}`, `{1}`, and so on # #[error_chain(custom)] #[error_chain(display = const("invalid toolchain name: '{0}'"))] InvalidToolchainName(String),
# # // Struct variants use `{name_of_the_field}` # #[error_chain(custom)] #[error_chain(display = const("invalid toolchain name: '{name}'"))] InvalidToolchainName { name: String },
- 链式链接:转发到链式 errorkind 的
-
#[error_chain(原因= "some_function_expression")]
指定一个函数表达式,用于在生成的
Error
上实现::std::fmt::Error::cause()
这可以是一个内联lambda
# # #[error_chain(custom)] #[error_chain(cause = "|_, err| err")] Io(::std::path::PathBuf, ::std::io::Error),
或者它可以是单独的函数
# # #[error_chain(custom)] #[error_chain(cause = "parse_file_error_cause")] Io(::std::path::PathBuf, ::std::io::Error), // <snip> fn parse_file_error_cause<'a>(_: &::std::path::Path, err: &'a ::std::io::Error) -> &'a ::std::error::Error { err }
函数表达式必须具有以下签名:
(...) -> &::std::error::Error
。它应该为变体的每个字段有一个参数。字段通过引用传递。结果是包装在Option::Some()
中,以从::std::error::Error::cause()
因此,在上面的例子中,由于
Io
有两个类型为::std::path::PathBuf
和::std::io::Error
的字段,函数表达式需要具有类型(&::std::path::Path, &::std::io::Error) -> &::std::error::Error
如果没有指定,
::std::error::Error::cause()
的默认实现将按这种方式行为- 链式链接:返回
None
- 外部链接:转发到外部错误的
::std::error::Error::cause()
实现中 - 自定义链接:返回
None
当启用
proc_macro
功能时,不需要将值字符串化# # # #[error_chain(custom)] #[error_chain(cause = |_, err| err)] Io(::std::path::PathBuf, ::std::io::Error),
# # # #[error_chain(custom)] #[error_chain(cause = parse_file_error_cause)] Io(::std::path::PathBuf, ::std::io::Error), #
- 链式链接:返回
当启用 proc_macro
功能时,与 error-chain
宏冲突
如果您启用了 proc_macro
功能并且有如下代码:
#![feature(proc_macro)]
#[macro_use] extern crate derive_error_chain;
#[macro_use] extern crate error_chain; // Want to use `bail!` and `quick_main!`
#[derive(Debug, ErrorChain)]
#[error_chain(result = "MyResult")]
enum ErrorKind {
Msg(String),
}
quick_main!(|| -> MyResult<()> {
bail!("failed");
});
它将无法编译
error: macro `error_chain` may not be used in attributes
这是因为在编译器看来,#[error_chain(result = "MyResult")]
是一个属性宏的调用,它注意到 error_chain!
是从 error-chain
包中引入的 macro_rules
宏,因此抱怨 macro_rules
宏不能用作属性宏。即使没有名为 error_chain
的属性宏,并且从这个包中自定义 derive 已将 error_chain
注册为支持的属性,它也会这样做。
有关讨论,请参阅 https://github.com/rust-lang/rust/issues/38356#issuecomment-324277403
为了解决这个问题,不要在 error-chain
包中使用 #[macro_use]
。相反,要么从其中 use
你需要的宏
#![feature(proc_macro)]
#[macro_use] extern crate derive_error_chain;
extern crate error_chain;
use error_chain::{ bail, quick_main };
#[derive(Debug, ErrorChain)]
#[error_chain(result = "MyResult")]
enum ErrorKind {
Msg(String),
}
quick_main!(|| -> MyResult<()> {
bail!("failed");
});
或者完全限定它们的路径
#![feature(proc_macro)]
#[macro_use] extern crate derive_error_chain;
extern crate error_chain;
#[derive(Debug, ErrorChain)]
#[error_chain(result = "MyResult")]
enum ErrorKind {
Msg(String),
}
error_chain::quick_main!(|| -> MyResult<()> {
error_chain::bail!("failed");
});
使用 error_chain!
宏本身更为复杂:它必须重命名,以防止再次产生上述错误,并且它使用的其他宏也必须导入,尽管它们是实现细节
#![feature(proc_macro)]
#[macro_use] extern crate derive_error_chain;
extern crate error_chain;
use error_chain::{ error_chain as error_chain_macro, error_chain_processing, impl_error_chain_kind, impl_error_chain_processed, impl_extract_backtrace };
#[derive(Debug, ErrorChain)]
#[error_chain(error = "MyError", result = "MyResult", result_ext = "MyResultExt")]
enum MyErrorKind {
Msg(String),
}
error_chain_macro! {
}
为了完全限定使用,它所依赖的宏仍然需要 use
来将其引入作用域
#![feature(proc_macro)]
#[macro_use] extern crate derive_error_chain;
extern crate error_chain;
use error_chain::{ error_chain_processing, impl_error_chain_kind, impl_error_chain_processed, impl_extract_backtrace };
#[derive(Debug, ErrorChain)]
#[error_chain(error = "MyError", result = "MyResult", result_ext = "MyResultExt")]
enum MyErrorKind {
Msg(String),
}
error_chain::error_chain! {
}
在 proc_macro
功能稳定之前,这个体验可能会变得更好。
依赖关系
~2MB
~47K SLoC