为什么匹配表达式不会报告其他武器之前的全能手臂(_)的错误?

时间:2018-05-31 12:38:35

标签: rust match warnings

Rust有一个名为match的构造,在其他语言中看起来与switch非常相似。但是我观察到match的一种非常特殊的行为。

let some_u32_value = 3;
match some_u32_value {
    _ => (),
    3 => println!("three"),
}

match尊重提及案例/模式的顺序。如果默认(_)案例位于顶部,为什么不报告错误?它确实发出警告:

warning: unreachable pattern
 --> src/main.rs:5:9
  |
5 |         3 => println!("three"),
  |         ^
  |
  = note: #[warn(unreachable_patterns)] on by default

Java中的类似构造,即switch,不保留任何顺序,因此在其他情况之前使用default不是错误(忽略行为的下降)。

int x = 0;

switch (x) {
  default:
    System.out.println("default");
    break;
  case 0:
      System.out.println("Zero");
} 

有明确的目的吗?

2 个答案:

答案 0 :(得分:4)

无法访问的模式并非严格意义上的错误,我的意思是:它不会阻止编译器理解"代码也不会使代码不安全。

同样,例如,在C中,您可以返回对局部变量的引用而不会触发错误(至少使用gcc):

#include <stdio.h>

int* foo() {
    int x = 0;

    return &x;
}

int main() {
    printf("%d", *foo());

    return 0;
}

一般情况下,您不应该将警告视为&#34;哦,那只只是警告,我不在乎&#34;。警告是编译器提供的实际有用的建议/信息。

我喜欢中给出的定义:

  

通常会发出警告,认识到潜在的高风险情况,可能的误解,服务质量下降或即将发生的失败。

因为它有助于理解错误和警告之间的区别:

  • 错误 错误,
  • 警告是潜在/可能的错误或有问题的事情。

在这种情况下,match的最后一个部分是一些死代码,因此编译器会相应地报告它。

答案 1 :(得分:3)

Rust的match表达式比Java switch语句强大得多,而且您可以做的不仅仅是匹配数字。

特别是,它支持模式匹配,它允许您根据数据的结构或其包含的值来匹配数据。如果要匹配更复杂的模式,则能够指定顺序非常重要,因为模式可能会重叠。例如:

let value = Some((Some(3), "hello"));

let s = match value {
    None => "Nothing there!".to_owned(),
    Some((Some(3), _)) => "The number is exactly 3!".to_owned(),
    Some((Some(n), _)) if n > 3 => format!("Got a number bigger than 3: {}", n),
    Some((None, msg)) => format!("Message with no number: {}", msg),
    Some((_, msg)) => format!("Got the message, ignore the rest: {}", msg),
    _ => "Anything else?".to_owned()
};

println!("result = {}", s);

这里的最后一个案例实际上是不可能的,因为其他分支涵盖了一切。如果不是您想要的,编译器将发出警告。