`if let` 如果中间值不运行析构函数

rub*_*ubo 5 destructor rust

考虑两个语义等效的代码段:

let x = Mutex::new(0);
if *x.lock().unwrap() == 0 {
    *x.lock().unwrap() = 1;
}
Run Code Online (Sandbox Code Playgroud)
let x = Mutex::new(0);
if let 0 = *x.lock().unwrap() {
    *x.lock().unwrap() = 1;
}
Run Code Online (Sandbox Code Playgroud)

第一个按预期运行,而第二个则死锁。为什么守卫析构函数被运行if而不是被运行if let?在哪里可以找到有关此行为的文档?

Ale*_*nov 4

答案可以在 上找到docs.rust-lang.org。具体可以参考if let一篇文章,里面说:

表达式if let等效于match如下表达式:

if let PATS = EXPR { /* body */ } else { /*else */ }

相当于

match EXPR { PATS => { /* body */ }, _ => { /* else */ } }

转到match文章后,据说

根据检查表达式是位置表达式还是值表达式,匹配的行为会有所不同。

如果被检查者表达式是值表达式,则首先将其计算到临时位置,然后将结果值顺序与手臂中的模式进行比较,直到找到匹配。选择具有匹配模式的第一个臂作为匹配的分支目标,该模式绑定的任何变量都被分配给该臂块中的局部变量,并且控制进入该块。

...有关地点表达的更多信息

在您的情况下,scrutinee*x.lock().unwrap()是一个值表达式,因此守卫的生命周期与主分支的生命周期相同。因此你会陷入僵局,.lock()在它已经被你自己锁定后再次尝试互斥if let