From 2ce223a85196968b4ae3f9299e437f47e63a49d3 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Sat, 16 Nov 2024 14:52:42 +0500 Subject: [PATCH] Do not trigger if_let_mutex strating from Edition 2024 --- clippy_lints/src/if_let_mutex.rs | 11 ++++ tests/ui/if_let_mutex.rs | 6 +- tests/ui/if_let_mutex_2021.rs | 63 +++++++++++++++++++ ..._mutex.stderr => if_let_mutex_2021.stderr} | 8 +-- 4 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 tests/ui/if_let_mutex_2021.rs rename tests/ui/{if_let_mutex.stderr => if_let_mutex_2021.stderr} (93%) diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index ba80c099a015..2b72cc3825bc 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -7,6 +7,7 @@ use rustc_errors::Diag; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::edition::Edition::Edition2024; use rustc_span::sym; declare_clippy_lint! { @@ -14,6 +15,12 @@ declare_clippy_lint! { /// Checks for `Mutex::lock` calls in `if let` expression /// with lock calls in any of the else blocks. /// + /// ### Disabled starting in Edition 2024 + /// `Mutex::lock` is effectively disabled starting in + /// Edition 2024 as `if let ... else` scoping was reworked + /// such that this is no longer an issue. See + /// [Proposal: stabilize if_let_rescope for Edition 2024](https://github.com/rust-lang/rust/issues/131154) + /// /// ### Why is this bad? /// The Mutex lock remains held for the whole /// `if let ... else` block and deadlocks. @@ -45,6 +52,10 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]); impl<'tcx> LateLintPass<'tcx> for IfLetMutex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if cx.tcx.sess.edition() >= Edition2024 { + return; + } + if let Some(higher::IfLet { let_expr, if_then, diff --git a/tests/ui/if_let_mutex.rs b/tests/ui/if_let_mutex.rs index bb0eadfca1c7..0116d4bbcf3a 100644 --- a/tests/ui/if_let_mutex.rs +++ b/tests/ui/if_let_mutex.rs @@ -1,3 +1,6 @@ +//@ compile-flags: -Zunstable-options + +//@edition:2024 #![warn(clippy::if_let_mutex)] #![allow(clippy::redundant_pattern_matching)] @@ -9,7 +12,6 @@ fn do_stuff(_: T) {} fn if_let() { let m = Mutex::new(1_u8); if let Err(locked) = m.lock() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d do_stuff(locked); } else { let lock = m.lock().unwrap(); @@ -22,7 +24,6 @@ fn if_let() { fn if_let_option() { let m = Mutex::new(Some(0_u8)); if let Some(locked) = m.lock().unwrap().deref() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d do_stuff(locked); } else { let lock = m.lock().unwrap(); @@ -44,7 +45,6 @@ fn if_let_different_mutex() { fn mutex_ref(mutex: &Mutex) { if let Ok(i) = mutex.lock() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d do_stuff(i); } else { let _x = mutex.lock(); diff --git a/tests/ui/if_let_mutex_2021.rs b/tests/ui/if_let_mutex_2021.rs new file mode 100644 index 000000000000..db310f88296f --- /dev/null +++ b/tests/ui/if_let_mutex_2021.rs @@ -0,0 +1,63 @@ +//@edition:2021 +#![warn(clippy::if_let_mutex)] +#![allow(clippy::redundant_pattern_matching)] + +use std::ops::Deref; +use std::sync::Mutex; + +fn do_stuff(_: T) {} + +fn if_let() { + let m = Mutex::new(1_u8); + if let Err(locked) = m.lock() { + //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + do_stuff(locked); + } else { + let lock = m.lock().unwrap(); + do_stuff(lock); + }; +} + +// This is the most common case as the above case is pretty +// contrived. +fn if_let_option() { + let m = Mutex::new(Some(0_u8)); + if let Some(locked) = m.lock().unwrap().deref() { + //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + do_stuff(locked); + } else { + let lock = m.lock().unwrap(); + do_stuff(lock); + }; +} + +// When mutexes are different don't warn +fn if_let_different_mutex() { + let m = Mutex::new(Some(0_u8)); + let other = Mutex::new(None::); + if let Some(locked) = m.lock().unwrap().deref() { + do_stuff(locked); + } else { + let lock = other.lock().unwrap(); + do_stuff(lock); + }; +} + +fn mutex_ref(mutex: &Mutex) { + if let Ok(i) = mutex.lock() { + //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + do_stuff(i); + } else { + let _x = mutex.lock(); + }; +} + +fn multiple_mutexes(m1: &Mutex<()>, m2: &Mutex<()>) { + if let Ok(_) = m1.lock() { + m2.lock(); + } else { + m1.lock(); + } +} + +fn main() {} diff --git a/tests/ui/if_let_mutex.stderr b/tests/ui/if_let_mutex_2021.stderr similarity index 93% rename from tests/ui/if_let_mutex.stderr rename to tests/ui/if_let_mutex_2021.stderr index 45df4ac4d679..20ee4b735140 100644 --- a/tests/ui/if_let_mutex.stderr +++ b/tests/ui/if_let_mutex_2021.stderr @@ -1,5 +1,5 @@ error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:11:5 + --> tests/ui/if_let_mutex_2021.rs:12:5 | LL | if let Err(locked) = m.lock() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -19,7 +19,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::if_let_mutex)]` error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:24:5 + --> tests/ui/if_let_mutex_2021.rs:25:5 | LL | if let Some(locked) = m.lock().unwrap().deref() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -37,7 +37,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:46:5 + --> tests/ui/if_let_mutex_2021.rs:47:5 | LL | if let Ok(i) = mutex.lock() { | ^ ----- this Mutex will remain locked for the entire `if let`-block... @@ -54,7 +54,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:55:5 + --> tests/ui/if_let_mutex_2021.rs:56:5 | LL | if let Ok(_) = m1.lock() { | ^ -- this Mutex will remain locked for the entire `if let`-block...