rust 未涵盖枚举选项

2guxujil  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(70)
enum Shot {
    Bullseye,
    Hit(f64),
    Miss
}

impl Shot {
    fn points(self) -> i32 {
        match self {
            Shot::Bullseye => 5,
            Shot::Hit(x) if x < 3.0 => 2, 
            Shot::Hit(x) if x >= 3.0 => 1, 
            Shot::Miss => 0
        }
    }
}

字符串

获取错误:

error[E0004]: non-exhaustive patterns: `Shot::Hit(_)` not covered
  --> src/main.rs:23:15
   |
23 |         match self {
   |               ^^^^ pattern `Shot::Hit(_)` not covered
   |
note: `Shot` defined here
  --> src/main.rs:15:5
   |
13 | enum Shot {
   |      ----
14 |     Bullseye,
15 |     Hit(f64),
   |     ^^^ not covered

8iwquhpp

8iwquhpp1#

你有两个问题。第一种是使用非穷举匹配臂,第二种是使用浮点数。为了单独讨论它们,让我们将Shot::Hit变量改为i32而不是f64

enum Shot {
    Bullseye,
    Hit(i32),
    Miss
}

impl Shot {
    fn points(self) -> i32 {
        match self {
            Shot::Bullseye => 5,
            Shot::Hit(x) if x < 3 => 2, 
            Shot::Hit(x) if x >= 3 => 1, 
            Shot::Miss => 0
        }
    }
}

字符串
这仍然不会编译与非常相似的错误消息。这是因为铁 rust 不够“聪明”,看不出那两只手臂确实是穷尽的。告诉rust它们是的惯用方法是添加分支Shot::Hit(_)并告诉它是unreachable!

match self {
    Shot::Bullseye => 5,
    Shot::Hit(x) if x < 3 => 2, 
    Shot::Hit(x) if x >= 3 => 1,
    Shot::Hit(_) => {
        unreachable!("all integers are either greater that 3 or less or equal to 3")
    }
    Shot::Miss => 0
}


如果这个分支在运行时被匹配,那么程序将死机,这通常是一件正确的事情(因为这一定是一个bug)。
然而,如果我们回到浮点数,这仍然不够。罪魁祸首当然是NaNf32/64只实现PartialEqPartialOrd而不实现EqOrd的原因)。
你必须决定NaN是否是你允许Shot::Hit持有的值。如果
不可能**,您可以忽略这种情况,只使用unreachable!。但如果这种情况发生,您也应该匹配该案例

match self {
    Shot::Bullseye => 5,
    Shot::Hit(x) if x < 3 => 2, 
    Shot::Hit(x) if x >= 3 => 1,
    // Note that we cannot say `if x == f64::NAN`, since `NaN != NaN`.
    Shot::Hit(x) if x.is_nan() => todo!(),
    Shot::Hit(_) => unreachable!("we should be clear now"),
    Shot::Miss => 0
}

bf1o4zei

bf1o4zei2#

Rust不会尝试检查if分支的穷尽性,因此它会认为您缺少Shot::Hit(x) => todo!(),的默认值。
在这种情况下,解决方案将是删除第二个if,并且只有:

match self {
    Shot::Bullseye => 5,
    Shot::Hit(x) if x < 3.0 => 2, 
    Shot::Hit(x) => 1, 
    Shot::Miss => 0
}

字符串

相关问题