为什么在Rust中'match`比' if`拥有更长的引用?

wnavrhmk  于 2023-01-30  发布在  其他
关注(0)|答案(1)|浏览(150)

注意到Rust中matchif在生存期方面的以下差异-假设我们有简单的结构:

struct Foo;

impl Foo {
  is_valid(&self) -> bool { true }
}

和一个保存它的互斥锁

let foo = tokio::sync::Mutex::new(Foo);

对于以下match,锁一直存在到match构造结束:

match foo.lock().await.is_valid() {
  _ => foo.lock().await.is_valid(), // Deadlock.
};

这不会完成,因为当第二行尝试获取锁时,锁仍然保持。但是使用if将在计算bool后立即释放第一个锁:

if foo.lock().await.is_valid() {
  foo.lock().await.is_valid(); // This is fine.
}

这段代码结束时锁被使用了两次。这是否意味着matchif挂起的引用更多?对此有何解释?

0g0grzrc

0g0grzrc1#

我相信this issue会给予你你要找的信息。
简言之,Drop trait是在match语句中的所有内容都被解析之后触发的,这意味着在调用内部锁时,外部锁还没有被释放,对于if语句,Drop trait是在检查条件之后、调用条件块之前立即调用的。
有趣的是,if let表达式似乎也会发生这种情况。下面的代码也会死锁:

struct Foo;

impl Foo {
    fn is_valid(&self) -> bool { true }
}

#[tokio::main]
async fn main() {
    let foo = tokio::sync::Mutex::new(Foo);

    if let true = foo.lock().await.is_valid() {
        foo.lock().await.is_valid();
    };
}

相关问题