std::io::ErrorKind有变种__Nonexhaustive.如果这个变体不存在,我不知道是什么问题.
这个变种的目的是什么?
huo*_*uon 18
它旨在ErrorKind通过强制match使用稳定代码中的任何语句来实现全面的扩展,从而允许将来扩展枚举_.
具体来说,变量标记为不稳定,因此不能在稳定通道上引用,因此编译器会拒绝代码
fn foo(x: Error) {
match x.kind() {
ErrorKind::NotFound => {}
ErrorKind::PermissionDenied => {}
ErrorKind::ConnectionRefused => {}
ErrorKind::ConnectionReset => {}
ErrorKind::ConnectionAborted => {}
ErrorKind::NotConnected => {}
ErrorKind::AddrInUse => {}
ErrorKind::AddrNotAvailable => {}
ErrorKind::BrokenPipe => {}
ErrorKind::AlreadyExists => {}
ErrorKind::WouldBlock => {}
ErrorKind::InvalidInput => {}
ErrorKind::InvalidData => {}
ErrorKind::TimedOut => {}
ErrorKind::WriteZero => {}
ErrorKind::Interrupted => {}
ErrorKind::Other => {}
ErrorKind::UnexpectedEof => {}
ErrorKind::UnexpectedEOF => {}
ErrorKind::__Nonexhaustive => {}
}
}
Run Code Online (Sandbox Code Playgroud)
<anon>:24:9: 24:35 error: use of unstable library feature 'io_error_internals': better expressed through extensible enums that this enum cannot be exhaustively matched against (see issue #0)
<anon>:24 ErrorKind::__Nonexhaustive => {}
^~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
如果此代码在稳定的Rust上成功编译,那么ErrorKind在将来的版本中添加一个变体会破坏任何match类似上面的代码,并且破坏稳定的代码是不好的.代码中断因为Rust中的匹配必须是详尽的,也就是说,它们必须以某种方式涵盖所有可能性,因此添加变量意味着不包括可能性.
相反,程序员必须写:
fn foo(x: Error) {
match x.kind() {
ErrorKind::NotFound => {}
ErrorKind::PermissionDenied => {}
ErrorKind::ConnectionRefused => {}
ErrorKind::ConnectionReset => {}
ErrorKind::ConnectionAborted => {}
ErrorKind::NotConnected => {}
ErrorKind::AddrInUse => {}
ErrorKind::AddrNotAvailable => {}
ErrorKind::BrokenPipe => {}
ErrorKind::AlreadyExists => {}
ErrorKind::WouldBlock => {}
ErrorKind::InvalidInput => {}
ErrorKind::InvalidData => {}
ErrorKind::TimedOut => {}
ErrorKind::WriteZero => {}
ErrorKind::Interrupted => {}
ErrorKind::Other => {}
ErrorKind::UnexpectedEof => {}
ErrorKind::UnexpectedEOF => {}
_ => {}
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着ErrorKind将来添加的任何变体(例如,新IO功能的新错误可能性)将落在_手臂下,因此现有的稳定代码不会中断.
这个隐藏变体的目的是阻止你写这样的东西(因为存在而不能精确编译__Nonexhaustive):
use std::io::ErrorKind;
fn main() {
let error_kind: ErrorKind = unimplemented!();
match error_kind {
ErrorKind::NotFound => unimplemented!(),
ErrorKind::PermissionDenied => unimplemented!(),
ErrorKind::ConnectionRefused => unimplemented!(),
ErrorKind::ConnectionReset => unimplemented!(),
ErrorKind::ConnectionAborted => unimplemented!(),
ErrorKind::NotConnected => unimplemented!(),
ErrorKind::AddrInUse => unimplemented!(),
ErrorKind::AddrNotAvailable => unimplemented!(),
ErrorKind::BrokenPipe => unimplemented!(),
ErrorKind::AlreadyExists => unimplemented!(),
ErrorKind::WouldBlock => unimplemented!(),
ErrorKind::InvalidInput => unimplemented!(),
ErrorKind::InvalidData => unimplemented!(),
ErrorKind::TimedOut => unimplemented!(),
ErrorKind::WriteZero => unimplemented!(),
ErrorKind::Interrupted => unimplemented!(),
ErrorKind::Other => unimplemented!(),
ErrorKind::UnexpectedEOF => unimplemented!(),
ErrorKind::UnexpectedEof => unimplemented!(),
// note: no wildcard match arm here
};
}
Run Code Online (Sandbox Code Playgroud)
究其原因,为什么标准库的开发者不希望你这样做是为了保留变种增加的能力ErrorKind的未来.该__Nonexhaustive变体可以通过简单地处理每个变体来阻止您进行详尽的匹配; 你必须有一个通配符臂才能进行详尽的匹配.
在Rust中,match表达式要求匹配的表达式的所有可能模式都具有相应的arm,以便match表达式始终具有明确定义的显式值.match涵盖所有模式的A 称为穷举匹配.使用enums,Rust让我们只列出所有变体.例如,对于Option,其中只有2个变种,命名为None和Some,我们可以这样写:
fn main() {
let option: Option<()> = unimplemented!();
match option {
None => unimplemented!(),
Some(()) => unimplemented!(),
};
}
Run Code Online (Sandbox Code Playgroud)
这match编译好,因为它涵盖了所有可能的模式进行option.但是,如果Option类型获得了另一个变体,那么突然你的代码将不再编译,因为它将不再是详尽无遗的.当然,这没有意义Option,所以这种Option类型不会发挥"非穷尽"游戏.但如果__Nonexhaustive不存在,添加一个变体ErrorKind将是一个突破性的变化; 任何完全匹配(没有通配符)的代码ErrorKind都会突然停止编译.此代码可能位于您的应用程序所依赖的包中,并且该破坏可能会阻止您升级Rust,直到该包修复为止!
| 归档时间: |
|
| 查看次数: |
905 次 |
| 最近记录: |