此代码立即完成(playground):
use std::sync::Mutex;
fn f(_: usize, _: usize) {}
fn main() {
let m = Mutex::new(0);
let i = { *m.lock().unwrap() };
let j = { *m.lock().unwrap() };
f(i, j);
}
此代码也立即完成(playground):
use std::sync::Mutex;
fn f(_: usize, _: usize) {}
fn main() {
let m = Mutex::new(0);
f(
{
let i = *m.lock().unwrap();
i
},
{
let j = *m.lock().unwrap();
j
},
);
}
这段代码,我认为在语义上与上面的代码相同,永远阻塞(playground):
use std::sync::Mutex;
fn f(_: usize, _: usize) {}
fn main() {
let m = Mutex::new(0);
f({ *m.lock().unwrap() }, { *m.lock().unwrap() });
}
为什么?
发生这种情况是由于 临时范围。
表达式的临时作用域是用于临时变量的作用域,该临时变量在位置上下文中使用时保存该表达式的结果,除非它被提升。
除了生命周期扩展之外,表达式的临时作用域是包含该表达式的最小作用域,并且是以下之一:
- 整个功能。
- 声明。
、if
或while
表达式的主体。loop
表达式的else
块。if
或if
表达式或while
保护的条件表达式。match
- 火柴臂的身体表情。
- 惰性布尔表达式的第二个操作数。
在第三个示例中,适用于临时匹配守卫的最小范围是包含对
f
的调用的整个语句。 (请注意,块中的最终表达式不是语句。)
因此,您的第二个和第三个代码示例在语义上“不”相同。在第三个示例中,在块表达式中创建的互斥锁保护的生命周期扩展到调用 f
的整个语句,但在第二个示例中,互斥锁保护的生命周期仅限于 let
语句。