Rust中match表达式末尾加分号解决借用检查器问题的原因
Rust借用检查器问题:为何match后加分号能解决E0597?
我遇到一个Rust借用检查器的问题:当注释掉match表达式后的println!语句时,编译器会抛出E0597错误,提示在match末尾加个分号就能解决,但我搞不懂为什么需要这么做。
代码示例
use std::sync::{Arc, Mutex}; #[derive(Default)] struct A { b: Arc<Mutex<B>>, } #[derive(Default)] struct B { c: Arc<Mutex<C>>, } #[derive(Default)] struct C { d: i32, } fn main() { let a = A::default(); match a.b.lock().unwrap().c.lock().unwrap().d { 0 => println!("zero"), _ => println!("non-zero"), } // 取消注释下方语句可让借用检查器通过 // println!("{}", a.b.lock().unwrap().c.lock().unwrap().d); }
错误信息
error[E0597]: `a.b` does not live long enough --> src/main.rs:21:11 | 19 | let a = A::default(); | - binding `a` declared here 20 | 21 | match a.b.lock().unwrap().c.lock().unwrap().d { | ^^^---------------- | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... ... 27 | } | - | | | `a.b` dropped here while still borrowed | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` | help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped | 24 | }; | + For more information about this error, try `rustc --explain E0597`.
问题原因解析
核心在于临时变量的销毁时机:
- Rust中,不带分号的表达式会作为所在代码块的返回值,它的临时值(比如这里调用
lock()得到的MutexGuard)会存活到整个块结束。在你的代码里,当没有println!时,match是main函数的最后一个表达式,那些MutexGuard会一直存活到main函数末尾,也就是a被销毁之后。但MutexGuard持有a.b的借用,这就导致a先被销毁,而借用还存在,违反了借用规则,触发E0597。 - 给match加上分号后,它从一个表达式变成了一条语句。语句的临时值会在语句执行完成后立刻销毁,也就是在
a还存活的时候,MutexGuard就已经被释放,借用也随之结束,不会和a的销毁顺序冲突。
那为什么注释掉println!就出问题?因为当有println!时,main函数的最后一个表达式是println!,match作为前面的语句,它的临时值会在println!执行前就被销毁,借用提前释放,自然不会和a的销毁产生冲突。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

