Open
Description
Summary
For example, if a mutex is locked and its value is matched in the match condition, the lock is actually held for the duration of the entire match and is not dropped early due to lifetime extension rules.
This could easily become problematic because usually it's expected that the futures are Send
and due to the mutex guard being not Send
holding it across await points also makes the futures not Send
.
As such, one can wrap the condition in a block to narrow the scope of the mutex guard. However clippy gets angry and suggests to remove the block which in turn extends the scope and breaks the code.
Lint Name
blocks_in_conditions
Reproducer
tokio::spawn(async {
let state = Mutex::new(10i32);
// Clippy gets angry about this block.
// However code does not compile if we remove it.
match { *state.lock().unwrap() } {
1 .. 20 => {
// Futures which hold a lock across await points are not `Send`,
// so if the block above is removed, it's no longer possible to spawn
// it because `tokio::spawn` requires futures to be `Send`.
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
_ => {}
};
});
I saw this happen:
warning: omit braces around single expression condition
--> src/main.rs:46:11
|
46 | match { *state.lock().unwrap() } {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*state.lock().unwrap()`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_conditions
I expected to not actually see this lint at all.
Version
clippy 0.1.89 (bf64d66bd5 2025-05-21)