Rust中non_exhaustive的enum使用确保程序健壮性

 更新时间:2023年11月03日 10:29:17   作者:da_miao_zi  
这篇文章主要为大家介绍了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_exhaustiveenum,会发生什么呢?

以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()就对应成功的结果)。

而根据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 Channelnon_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使用确保程序健壮性的详细内容,更多关于Rust 的资料请关注脚本之家其它相关文章!

相关文章

  • rust zip异步压缩与解压的代码详解

    rust zip异步压缩与解压的代码详解

    在使用actix-web框架的时候,如果使用zip解压任务将会占用一个工作线程,因为zip库是同步阻塞的,想用异步非阻塞需要用另一个库,下面介绍下rust zip异步压缩与解压的示例,感兴趣的朋友一起看看吧
    2024-04-04
  • Rust实现面向对象的方法

    Rust实现面向对象的方法

    这篇文章主要介绍了Rust实现面向对象的方法,Rust 并不是面向对象的语言,但是面向对象的功能都可以通过自身的特点来实现,本文通过示例代码给大家详细讲解,需要的朋友可以参考下
    2022-10-10
  • Rust错误处理之`foo(...)?`的用法与错误类型转换小结

    Rust错误处理之`foo(...)?`的用法与错误类型转换小结

    foo(...)?语法糖为Rust的错误处理提供了极大的便利,通过结合map_err方法和From trait的实现,你可以轻松地处理不同类型的错误,并保持代码的简洁性和可读性,这篇文章主要介绍了Rust错误处理:`foo(...)?`的用法与错误类型转换,需要的朋友可以参考下
    2024-05-05
  • 详解Rust中的workspace

    详解Rust中的workspace

    这篇文章主要向大家介绍Rust中的workspace,主要内容包括基础应用、实用技巧、原理机制等方面,这个概念在Rust中是通用的,只不过maven换成了cargo,而模块变成了crate,下面跟着小编通过一个例子给大家介绍下
    2022-03-03
  • Rust use关键字妙用及模块内容拆分方法

    Rust use关键字妙用及模块内容拆分方法

    这篇文章主要介绍了Rust use关键字妙用|模块内容拆分,文中还给大家介绍use关键字的习惯用法,快速引用自定义模块内容或标准库,以此优化代码书写,需要的朋友可以参考下
    2022-09-09
  • Rust重载运算符之复数四则运算的实现

    Rust重载运算符之复数四则运算的实现

    这篇文章主要为大家详细介绍了Rust如何实现复数以及复数的四则运算,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-08-08
  • Rust 语言的全链路追踪库 tracing使用方法

    Rust 语言的全链路追踪库 tracing使用方法

    这篇文章主要介绍了Rust 语言的全链路追踪库 tracing,接下来就以 tracing 为例,介绍一下trace 的核心概念以及使用方法,需要的朋友可以参考下
    2022-12-12
  • rust智能指针的具体使用

    rust智能指针的具体使用

    智能指针是一些数据结构,它们的行为类似于指针但拥有额外的元数据和附加功能,本文就来介绍一下rust智能指针的具体使用,感兴趣的可以了解一下
    2023-12-12
  • Rust 的 into_owned() 方法实例详解

    Rust 的 into_owned() 方法实例详解

    into_owned是Rust语言中std::borrow::Cow 枚举的一个方法,into_owned确保了调用者获得数据的独立所有权,无论Cow之前是引用还是已经拥有数据,本文给大家介绍Rust 的 into_owned() 方法,感兴趣的的朋友跟随小编一起看看吧
    2024-03-03
  • Rust Option类型基本使用详解

    Rust Option类型基本使用详解

    Rust的Option是一种强大的类型,用于处理可能为空的情况,避免了许多空值引起的运行时错误,本文介绍Rust Option类型详解,感兴趣的朋友一起看看吧
    2024-02-02

最新评论