Rust中non_exhaustive的enum使用確保程序健壯性

Rust中non_exhaustive的enum
所謂non_exhaustive的enum就是定義中帶有#[non_exhaustive]的enum,如
#[non_exhaustive]
pub enum Error {
Message(String),
Other,
}在定義了這個enum的crate中,non_exhaustive沒有任何效果。
let error = Error::Other;
// Non-exhaustive enums can be matched on exhaustively within the defining crate.
match error {
Error::Message(ref s) => { },
Error::Other => { },
}但若引用的crate中存在non_exhaustive的enum,會發(fā)生什么呢?
以libpnet這個crate為例
在https://docs.rs/pnet/latest/pnet/#這個頁面給出的示例代碼中,可以看到這么一段
// Create a new channel, dealing with layer 2 packets
let (mut tx, mut rx) = match datalink::channel(&interface, Default::default()) {
Ok(Ethernet(tx, rx)) => (tx, rx),
Ok(_) => panic!("Unhandled channel type"),
Err(e) => panic!("An error occurred when creating the datalink channel: {}", e)
};datalink::channel()的返回值類型為Result<Channel, Error>,而Channel的類型是一個enum,
pub enum Channel {
Ethernet(Box<dyn DataLinkSender, Global>, Box<dyn DataLinkReceiver, Global>),
}atalink::channel()返回結果分析
如果datalink::channel()返回的是成功的結果(類型為Channel),將與第一個Ok(Ethernet(tx, rx))模式的前半部分匹配(因為Ok()就對應成功的結果)。
而根據(jù)Channel的定義,Channel::Ethernet(tx, rx)是該enum唯一的成員(variant),所以只要是成功的結果,就應該匹配第1個模式,否則就匹配最后的Err(e)這個模式。
這看起來滿足Rust中的匹配必須是窮舉式的(exhaustive)這一要求。因此似乎第2個模式Ok(_) => ,就顯得多余了。但若去掉這行,編譯時就會報錯Ok(_) not covered:
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
--> src/main.rs:33:31
|
33 | let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
|
note: `Result<Channel, std::io::Error>` defined here
...
|
= note: not covered
= note: the matched value is of type `Result<Channel, std::io::Error>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
38 ~ },
39 + Ok(_) => todo!()
|
For more information about this error, try `rustc --explain E0004`.這背后的原因就是因為enum Channel是non_exhaustive的,其完整定義是
// https://docs.rs/pnet_datalink/0.34.0/src/pnet_datalink/lib.rs.html#99
/// A channel for sending and receiving at the data link layer.
#[non_exhaustive]
pub enum Channel {
/// A datalink channel which sends and receives Ethernet packets.
Ethernet(Box<dyn DataLinkSender>, Box<dyn DataLinkReceiver>),
}而我們又在外部引用了包含這個enum的crate。解決的辦法就是加入Ok(_) => {...}。
感覺這應該算Rust確保程序健壯性(魯棒性)的一方面,在編譯階段就報出潛在的錯誤——咱也不知道引用的crate什么時候會在enum中增加新的成員。
參考
https://doc.rust-lang.org/beta/reference/attributes/type_syst... Type system attributes
https://docs.rs/pnet/latest/pnet/#examples This (fairly useless) code implements an Ethernet echo server.
以上就是Rust中non_exhaustive的enum使用確保程序健壯性的詳細內(nèi)容,更多關于Rust 的資料請關注腳本之家其它相關文章!
相關文章
Rust錯誤處理之`foo(...)?`的用法與錯誤類型轉換小結
foo(...)?語法糖為Rust的錯誤處理提供了極大的便利,通過結合map_err方法和From?trait的實現(xiàn),你可以輕松地處理不同類型的錯誤,并保持代碼的簡潔性和可讀性,這篇文章主要介紹了Rust錯誤處理:`foo(...)?`的用法與錯誤類型轉換,需要的朋友可以參考下2024-05-05
Rust重載運算符之復數(shù)四則運算的實現(xiàn)
這篇文章主要為大家詳細介紹了Rust如何實現(xiàn)復數(shù)以及復數(shù)的四則運算,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-08-08

