PartialEq/Eq正常工作时为什么匹配不起作用?

use*_*932 0 rust

我有这个简单的代码:

#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
struct NodeIndex(u32);

fn main() {
    let i = NodeIndex(5323);
    let from = NodeIndex(21030);
    let to = NodeIndex(21031);

    println!("from == i => {}, to == i => {}", from == i, to == i);

    match i {
        from => println!("1"),
        to => println!("2"),
        _ => println!("other"),
    }
}
Run Code Online (Sandbox Code Playgroud)

它打印:

from == i => false, to == i => false
1
Run Code Online (Sandbox Code Playgroud)

所以i != from,i != to但是match打电话from => println!("1"),,发生了什么事?

E_n*_*ate 6

通过查看编译器的警告可能更容易理解发生了什么:

warning: unused variable: `from`
  --> src/main.rs:12:9
   |
12 |         from => println!("1"),
   |         ^^^^
   |
   = note: #[warn(unused_variables)] on by default

warning: unreachable pattern
  --> src/main.rs:13:9
   |
13 |         to => println!("2"),
   |         ^^ this is an unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default
note: this pattern matches any value
  --> src/main.rs:12:9
   |
12 |         from => println!("1"),
   |         ^^^^

warning: unused variable: `to`
  --> src/main.rs:13:9
   |
13 |         to => println!("2"),
   |         ^^
   |
   = note: #[warn(unused_variables)] on by default

warning: unreachable pattern
  --> src/main.rs:14:9
   |
14 |         _ => println!("other"),
   |         ^ this is an unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default
note: this pattern matches any value
  --> src/main.rs:12:9
   |
12 |         from => println!("1"),
   |         ^^^^
Run Code Online (Sandbox Code Playgroud)

基本上,标识fromto 指包含在绑定的值.它们是碰巧匹配任何东西的绑定.新标识符名称也会发生同样的情况:

match i {
    x => println!("1"),
    y => println!("2"),
    _ => println!("other"),
}
Run Code Online (Sandbox Code Playgroud)

由于程序始终与第一种情况匹配,因此始终打印"1".

您可以通过声明得到预期的结果from,并toconst:

const from: NodeIndex = NodeIndex(21030);
const to: NodeIndex = NodeIndex(21031);
Run Code Online (Sandbox Code Playgroud)

或直接使用对象文字:

match i {
    NodeIndex(21030) => println!("1"),
    NodeIndex(21031) => println!("2"),
    _ => println!("other"),
}
Run Code Online (Sandbox Code Playgroud)

如果值fromto在运行时只知道,你可以使用if/ else语句:

if n == from {
    println!("1");
} else if n == to {
    println!("2");
} else {
    println!("other");
}
Run Code Online (Sandbox Code Playgroud)

...或if在匹配期间添加子句(在运行时评估):

match i {
    n if n == from => println!("1"),
    n if n == to => println!("2"),
    _ => println!("other"),
}
Run Code Online (Sandbox Code Playgroud)