E0004: non-exhaustive patterns の原因と直し方
match式は、値が取りうるすべてのパターンを網羅していなければコンパイルできません。一部のケースだけを書いて残りを省略すると、E0004エラーになります。
エラーメッセージの読み方
error[E0004]: non-exhaustive patterns: `Level::Advanced` not covered
E0004- エラーコード — `rustc --explain E0004` で詳しい説明が見られます
non-exhaustive patterns: `Level::Advanced` not covered- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 enum Level { Beginner, Intermediate, Advanced } 2 fn main() { 3 let level = Level::Intermediate; 4 let name = match level { 5 Level::Beginner => "beginner", 6 Level::Intermediate => "intermediate", ^ 7 }; 8 println!("{}", name); 9 }
match式はenumが取りうる全ての変体を網羅しなければコンパイルできません。Advancedのアームが抜けています。
直し方: Level::Intermediate => "intermediate", を Level::Intermediate => "intermediate",
Level::Advanced => "advanced", にします。
パターン2
1 enum Signal { Red, Yellow, Green } 2 fn main() { 3 let signal = Signal::Yellow; 4 let action = match signal { 5 Signal::Red => "stop", 6 Signal::Yellow => "caution", ^ 7 }; 8 println!("{}", action); 9 }
enumに新しい変体が増えたのにmatchのアームを追加し忘れると、このエラーが検出してくれます。
直し方: Signal::Yellow => "caution", を Signal::Yellow => "caution",
Signal::Green => "go", にします。
パターン3
1 enum Weather { Sunny, Rainy, Cloudy } 2 fn main() { 3 let w = Weather::Rainy; 4 let msg = match w { 5 Weather::Sunny => "bring sunscreen", 6 Weather::Rainy => "bring umbrella", ^ 7 }; 8 println!("{}", msg); 9 }
switch文がフォールスルーする言語と違い、Rustのmatchは網羅性チェックが必須です。
直し方: Weather::Rainy => "bring umbrella", を Weather::Rainy => "bring umbrella",
Weather::Cloudy => "bring jacket", にします。
パターン4
1 enum Size { Small, Medium, Large } 2 fn main() { 3 let s = Size::Medium; 4 let label = match s { 5 Size::Small => "S", 6 Size::Medium => "M", ^ 7 }; 8 println!("{}", label); 9 }
想定外の値を無視したい場合でも、_のワイルドカードアームを明示的に書く必要があります。
直し方: Size::Medium => "M", を Size::Medium => "M",
Size::Large => "L", にします。
パターン5
1 enum Role { Admin, Editor, Viewer } 2 fn main() { 3 let r = Role::Editor; 4 let perm = match r { 5 Role::Admin => "full", 6 Role::Editor => "write", ^ 7 }; 8 println!("{}", perm); 9 }
network-exhaustiveのチェックのおかげで、新しいバリアントの対応漏れをコンパイル時に発見できます。
直し方: Role::Editor => "write", を Role::Editor => "write",
Role::Viewer => "read", にします。
よくある誤解
「よくあるパターンだけ書いておけば、その他の値はスキップされて次に進むはず」という思い込みは誤りです。matchは網羅性チェックが必須で、想定外の値を無視したい場合でも_(ワイルドカード)のアームを明示する必要があります。
まとめ
E0004: non-exhaustive patternsは上級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。