2016-04-06 20 views
10

std::io::ErrorKindは、変異体__Nonexhaustiveを有する。 この亜種が存在しない場合、何が問題なのか分かりません。ErrorKindの目的は何ですか?

この亜種の目的は何ですか?

答えて

15

matchステートメントを安定コード内に強制的にキャッチオール_の腕を持つように設定することで、将来的に​​列挙型を拡張できるように設計されています。

バリアントを付加し、具体的には、the variant is marked unstableなどが安定したチャンネルで呼ぶことができず、このコードは、安定な錆で正常にコンパイルした場合ので、コンパイラは

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 => {} 
    } 
} 
<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 => {} 
        ^~~~~~~~~~~~~~~~~~~~~~~~~~ 

ようなコードを拒否将来のバージョンで​​に変更すると、上記のような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 => {} 
     _ => {} 
    } 
} 

これは、任意の変異体が、将来的に​​に(新しいIO機能用など新しいエラーの可能性)を追加したことを意味は、_腕の下に落ち、安定したコードウォンを既存ます壊れない

4

この隠された変種の目的は、(理由__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 
    }; 
} 

なぜ開発の理由標準ライブラリではこれをやりたくないのですが、将来は​​にバリアントを追加する機能を保持することです。 __Nonexhaustiveバリアントを使用すると、個々のバリアントを処理するだけで網羅的な一致を防ぐことができます。あなたには完全な一致を持つワイルドカードが必要です。

Rustでは、match式は、一致する式のすべての可能なパターンに対応する腕があることを要求するため、match式は常に明確で明示的な値を持ちます。すべてのパターンをカバーするmatchは、という完全なと一致します。 enumの場合、Rustはすべてのバリアントを単純にリストすることができます。たとえば、のみNoneSomeという名前の2つの変種を、持っているOption、と、私たちは書くことができます:それはoptionのためのすべての可能なパターンをカバーしているため

fn main() { 
    let option: Option<()> = unimplemented!(); 
    match option { 
     None => unimplemented!(), 
     Some(()) => unimplemented!(), 
    }; 
} 

これmatchは、罰金コンパイルします。しかし、Optionタイプが別のバリアントを取得した場合、コードはもはや網羅的ではないので、もはやコンパイルされません。もちろん、これはOptionでは意味をなさないので、Optionタイプは "非網羅的"ゲームを再生しません。しかし、__Nonexhaustiveが存在しない場合は、​​にバリアントを追加することは大きな変更になります。​​で完全一致(ワイルドカードなし)したコードは突然コンパイルを停止します。このコードはあなたのアプリケーションが依存している箱に入っている可能性があります。その破損によりクレートが修正されるまでRustをアップグレードできなくなる可能性があります。

関連する問題