可反驳性:模式是否可能无法匹配

模式有两种形式:可反驳和不可反驳。将匹配的模式 因为传递的任何可能的值都是无可辩驳的。一个例子是在 语句,因为匹配任何内容,因此不会失败 进行匹配。可能无法匹配某些可能值的模式是可反驳的。表达式中就是一个示例,因为如果变量中的值为 instead than ,则模式将不匹配。xlet x = 5;xSome(x)if let Some(x) = a_valuea_valueNoneSomeSome(x)

函数参数、语句和循环只能接受 irredefable 模式,因为当 值不匹配。和 表达式接受 rereftable 和 irrereftable 模式,但编译器会警告 无可辩驳的模式,因为根据定义,它们旨在处理可能的 failure:条件的功能在于其执行 根据成功或失败而有所不同。letforif letwhile let

一般来说,您不必担心 refutable 之间的区别 和无可辩驳的模式;但是,您确实需要熟悉这个概念 的可反驳性,以便您可以在错误消息中看到它时做出响应。在 在这些情况下,您需要更改模式或结构 使用模式,具体取决于代码的预期行为。

让我们看一个示例,当我们尝试使用可反驳模式时会发生什么 其中 Rust 需要一个无可辩驳的模式,反之亦然。示例 18-8 显示了一个语句,但对于我们指定的模式,一个可反驳的 模式。如您所料,此代码将无法编译。letSome(x)

fn main() {
    let some_option_value: Option<i32> = None;
    let Some(x) = some_option_value;
}

示例 18-8:尝试使用 let 的可反驳模式

如果是一个值,则它将无法匹配 pattern ,这意味着该模式是可反驳的。但是,该语句可以 只接受一个无可辩驳的模式,因为代码没有任何东西可以 do 与值一起使用。在编译时,Rust 会抱怨我们尝试了 在需要 irrefutable 模式的地方使用 refutable pattern:some_option_valueNoneSome(x)letNone

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0005]: refutable pattern in local binding
 --> src/main.rs:3:9
  |
3 |     let Some(x) = some_option_value;
  |         ^^^^^^^ pattern `None` not covered
  |
  = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
  = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
  = note: the matched value is of type `Option<i32>`
help: you might want to use `let else` to handle the variant that isn't matched
  |
3 |     let Some(x) = some_option_value else { todo!() };
  |                                     ++++++++++++++++

For more information about this error, try `rustc --explain E0005`.
error: could not compile `patterns` (bin "patterns") due to 1 previous error

因为我们没有覆盖(也无法覆盖)每个有效值 pattern 中,Rust 理所当然地会产生编译器错误。Some(x)

如果我们有一个 revertable 模式,而需要一个 irrefutable pattern ,我们可以 通过更改使用模式的代码来修复它:而不是使用 , 我们 可以使用 .然后,如果模式不匹配,代码将跳过 大括号中的代码,为其提供了一种有效继续的方法。清单 18-9 展示了如何修复示例 18-8 中的代码。letif let

fn main() {
    let some_option_value: Option<i32> = None;
    if let Some(x) = some_option_value {
        println!("{x}");
    }
}

示例 18-9:使用 if let 和带有 refutable 的块 patterns 而不是 let

我们已经给代码一个输出了!此代码现在完全有效。然而 如果我们给出一个无可辩驳的模式(一个始终会 match),如示例 18-10 所示,编译器将给出一个 警告。if letx

fn main() {
    if let x = 5 {
        println!("{x}");
    };
}

示例 18-10:尝试使用无可辩驳的模式 使用 if let

Rust 抱怨说,将 模式:if let

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
warning: irrefutable `if let` pattern
 --> src/main.rs:2:8
  |
2 |     if let x = 5 {
  |        ^^^^^^^^^
  |
  = note: this pattern will always match, so the `if let` is useless
  = help: consider replacing the `if let` with a `let`
  = note: `#[warn(irrefutable_let_patterns)]` on by default

warning: `patterns` (bin "patterns") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s
     Running `target/debug/patterns`
5

因此,match 分支必须使用可反驳的模式,除了最后一个 arm,它应该使用无可辩驳的模式匹配任何剩余值。锈 允许我们在只有一个臂的 a 中使用无可辩驳的模式,但是 此语法不是特别有用,可以替换为更简单的语句。matchlet

现在,您知道在何处使用模式以及 refutable 之间的区别 和无可辩驳的模式,让我们介绍一下我们可以用来创建 模式。

本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准