From a49b1fee43df522aa854396336e3e05a8a54249f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 4 Sep 2025 22:14:46 +0200 Subject: [PATCH 1/9] clean-up --- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/mut_mutex_lock.rs | 10 +++++----- clippy_utils/src/lib.rs | 10 +++++----- tests/ui/mut_mutex_lock.fixed | 1 - tests/ui/mut_mutex_lock.rs | 1 - tests/ui/mut_mutex_lock.stderr | 4 ++-- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 48842c8739c0..f4b2139b51e8 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -5360,7 +5360,7 @@ impl Methods { } }, (sym::lock, []) => { - mut_mutex_lock::check(cx, expr, recv, span); + mut_mutex_lock::check(cx, recv, span); }, (name @ (sym::map | sym::map_err), [m_arg]) => { if name == sym::map { diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index c9264e747b56..10fa14e4815f 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -9,12 +9,12 @@ use rustc_span::{Span, sym}; use super::MUT_MUTEX_LOCK; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>, recv: &'tcx Expr<'tcx>, name_span: Span) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_span: Span) { if matches!(expr_custom_deref_adjustment(cx, recv), None | Some(Mutability::Mut)) - && let (_, _, Some(Mutability::Mut)) = peel_and_count_ty_refs(cx.typeck_results().expr_ty(recv)) - && let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id) - && let Some(impl_id) = cx.tcx.impl_of_assoc(method_id) - && cx.tcx.type_of(impl_id).is_diag_item(cx, sym::Mutex) + // NOTE: the reason we don't use `expr_ty_adjusted` here is that a call to `Mutex::lock` by itself + // adjusts the receiver to be `&Mutex` + && let (recv_ty, _, Some(Mutability::Mut)) = peel_and_count_ty_refs(cx.typeck_results().expr_ty(recv)) + && recv_ty.is_diag_item(cx, sym::Mutex) { span_lint_and_sugg( cx, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 954c32687af6..88e493548f69 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -459,10 +459,9 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, owner: OwnerId) -> Opti /// This method will return tuple of projection stack and root of the expression, /// used in `can_mut_borrow_both`. /// -/// For example, if `e` represents the `v[0].a.b[x]` -/// this method will return a tuple, composed of a `Vec` -/// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]` -/// and an `Expr` for root of them, `v` +/// For example, if `e` represents the `v[0].a.b[x]` this method will return a tuple, composed of: +/// - a `Vec` containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]` +/// - and an `Expr` for root of them, `v` fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) { let mut result = vec![]; let root = loop { @@ -488,7 +487,8 @@ pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Optio Adjust::Deref(None) => None, _ => Some(None), }) - .and_then(|x| x) + // if there were no adjustments to begin with, trivially none of them are of the custom-deref kind + .unwrap_or(None) } /// Checks if two expressions can be mutably borrowed simultaneously diff --git a/tests/ui/mut_mutex_lock.fixed b/tests/ui/mut_mutex_lock.fixed index 5790ee8c1b02..44587b89ec83 100644 --- a/tests/ui/mut_mutex_lock.fixed +++ b/tests/ui/mut_mutex_lock.fixed @@ -1,4 +1,3 @@ -#![allow(dead_code, unused_mut)] #![warn(clippy::mut_mutex_lock)] use std::sync::{Arc, Mutex}; diff --git a/tests/ui/mut_mutex_lock.rs b/tests/ui/mut_mutex_lock.rs index 7286afac823b..eef4f26c0959 100644 --- a/tests/ui/mut_mutex_lock.rs +++ b/tests/ui/mut_mutex_lock.rs @@ -1,4 +1,3 @@ -#![allow(dead_code, unused_mut)] #![warn(clippy::mut_mutex_lock)] use std::sync::{Arc, Mutex}; diff --git a/tests/ui/mut_mutex_lock.stderr b/tests/ui/mut_mutex_lock.stderr index 67543c73c6ee..587405449523 100644 --- a/tests/ui/mut_mutex_lock.stderr +++ b/tests/ui/mut_mutex_lock.stderr @@ -1,5 +1,5 @@ error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:10:33 + --> tests/ui/mut_mutex_lock.rs:9:33 | LL | let mut value = value_mutex.lock().unwrap(); | ^^^^ help: change this to: `get_mut` @@ -8,7 +8,7 @@ LL | let mut value = value_mutex.lock().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::mut_mutex_lock)]` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:16:43 + --> tests/ui/mut_mutex_lock.rs:15:43 | LL | let mut value = mut_ref_mut_ref_mutex.lock().unwrap(); | ^^^^ help: change this to: `get_mut` From e95dbbf06a83df15423750e1494182bd54f92735 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 18 Dec 2025 13:30:10 +0100 Subject: [PATCH 2/9] fix(mut_mutex_lock): FP in projection chains --- clippy_lints/src/methods/mut_mutex_lock.rs | 41 +++- tests/ui/mut_mutex_lock.fixed | 243 +++++++++++++++++++++ tests/ui/mut_mutex_lock.rs | 243 +++++++++++++++++++++ tests/ui/mut_mutex_lock.stderr | 80 ++++++- 4 files changed, 600 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 10fa14e4815f..19e5356deb2c 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -3,18 +3,47 @@ use clippy_utils::expr_custom_deref_adjustment; use clippy_utils::res::MaybeDef; use clippy_utils::ty::peel_and_count_ty_refs; use rustc_errors::Applicability; -use rustc_hir::{Expr, Mutability}; +use rustc_hir::{Expr, ExprKind, Mutability}; use rustc_lint::LateContext; use rustc_span::{Span, sym}; use super::MUT_MUTEX_LOCK; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_span: Span) { - if matches!(expr_custom_deref_adjustment(cx, recv), None | Some(Mutability::Mut)) - // NOTE: the reason we don't use `expr_ty_adjusted` here is that a call to `Mutex::lock` by itself - // adjusts the receiver to be `&Mutex` - && let (recv_ty, _, Some(Mutability::Mut)) = peel_and_count_ty_refs(cx.typeck_results().expr_ty(recv)) - && recv_ty.is_diag_item(cx, sym::Mutex) + // given a `recv` like `a.b.mutex`, this returns `[a.b.mutex, a.b, a]` + let mut projection_chain = std::iter::successors(Some(recv), |recv| { + if let ExprKind::Index(r, ..) | ExprKind::Field(r, _) = recv.kind { + Some(r) + } else { + None + } + }); + + if (cx.typeck_results().expr_ty_adjusted(recv)) + .peel_refs() + .is_diag_item(cx, sym::Mutex) + // If, somewhere along the projection chain, we stumble upon a field of type `&T`, or dereference a + // type like `Arc` to `&T`, we no longer have mutable access to the undelying `Mutex` + && projection_chain.all(|recv| { + let expr_ty = cx.typeck_results().expr_ty(recv); + // The reason we don't use `expr_ty_adjusted` here is twofold: + // + // Consider code like this: + // ```rs + // struct Foo(Mutex); + // + // fn fun(f: &Foo) { + // f.0.lock() + // } + // ``` + // - In the outermost receiver (`f.0`), the adjusted type would be `&Mutex`, due to an adjustment + // performed by `Mutex::lock`. + // - In the intermediary receivers (here, only `f`), the adjusted type would be fully dereferenced + // (`Foo`), which would make us miss the fact that `f` is actually behind a `&` -- this + // information is preserved in the pre-adjustment type (`&Foo`) + peel_and_count_ty_refs(expr_ty).2 != Some(Mutability::Not) + && expr_custom_deref_adjustment(cx, recv) != Some(Mutability::Not) + }) { span_lint_and_sugg( cx, diff --git a/tests/ui/mut_mutex_lock.fixed b/tests/ui/mut_mutex_lock.fixed index 44587b89ec83..b81fc5544532 100644 --- a/tests/ui/mut_mutex_lock.fixed +++ b/tests/ui/mut_mutex_lock.fixed @@ -37,4 +37,247 @@ fn mut_ref_ref_mutex_lock() { *guard += 1; } +mod issue16253 { + use std::sync::{Arc, Mutex}; + + struct RefMutex(&'static Mutex); + impl RefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&Mutex`, we can't get to `&mut Mutex` no matter what `self` is + refself.0.lock().unwrap(); + refmutself.0.lock().unwrap(); + self.0.lock().unwrap(); + } + } + + struct ArcMutex(Arc>); + impl ArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &Mutex`, we can't get a `&mut Mutex` no matter what `self` is + refself.0.lock().unwrap(); + refmutself.0.lock().unwrap(); + self.0.lock().unwrap(); + } + } + + struct RefMutMutex(&'static mut Mutex); + impl RefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut Mutex`, we _can_ get a `&mut Mutex` if we have `self`/`&mut self` + refself.0.lock().unwrap(); + refmutself.0.get_mut().unwrap(); + //~^ mut_mutex_lock + self.0.get_mut().unwrap(); + //~^ mut_mutex_lock + } + } + + struct ValueMutex(Mutex); + impl ValueMutex { + fn foo(mut self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Mutex`, we _can_ get a `&mut Mutex` if we have `self`/`&mut self` + refself.0.lock().unwrap(); + refmutself.0.get_mut().unwrap(); + //~^ mut_mutex_lock + self.0.get_mut().unwrap(); + //~^ mut_mutex_lock + } + } + + struct RefRefMutex(&'static RefMutex); + impl RefRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&RefMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcRefMutex(Arc); + impl ArcRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &RefMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutRefMutex(&'static mut RefMutex); + impl RefMutRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut RefMutex = &mut &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ValueRefMutex(RefMutex); + impl ValueRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `RefMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefArcMutex(&'static ArcMutex); + impl RefArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &RefMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcArcMutex(Arc); + impl ArcArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &ArcMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutArcMutex(&'static mut ArcMutex); + impl RefMutArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut ArcMutex = &mut &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ValueArcMutex(ArcMutex); + impl ValueArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `ArcMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefRefMutMutex(&'static RefMutMutex); + impl RefRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&RefMutMutex = &&mut Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcRefMutMutex(Arc); + impl ArcRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &RefMutMutex = &&mut Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutRefMutMutex(&'static mut RefMutMutex); + impl RefMutRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut RefMutMutex = &mut &mut Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + self.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + } + } + + struct ValueRefMutMutex(RefMutMutex); + impl ValueRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `RefMutMutex = &mut Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + self.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + } + } + + struct RefValueMutex(&'static ValueMutex); + impl RefValueMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&ValueMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcValueMutex(Arc); + impl ArcValueMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &ValueMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutValueMutex(&'static mut ValueMutex); + impl RefMutValueMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut ValueMutex = &mut Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + self.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + } + } + + struct ValueValueMutex(ValueMutex); + impl ValueValueMutex { + fn foo(mut self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `ValueMutex = Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + self.0.0.get_mut().unwrap(); + //~^ mut_mutex_lock + } + } + + fn index(mutexes: &mut [Mutex]) { + // even though `[0]` is _currently_ an `.index(0)`, it can be turned into `.index_mut()` to + // enable mutable access: `&mut [Mutex] -> &mut Mutex` + mutexes[0].get_mut().unwrap(); + //~^ mut_mutex_lock + + // `exes` is `&[Mutex] = &Mutex`, so we can't get to `&mut Mutex` no matter what + let exes: &_ = mutexes; + exes[0].lock().unwrap(); + } +} + fn main() {} diff --git a/tests/ui/mut_mutex_lock.rs b/tests/ui/mut_mutex_lock.rs index eef4f26c0959..521dab9560ac 100644 --- a/tests/ui/mut_mutex_lock.rs +++ b/tests/ui/mut_mutex_lock.rs @@ -37,4 +37,247 @@ fn mut_ref_ref_mutex_lock() { *guard += 1; } +mod issue16253 { + use std::sync::{Arc, Mutex}; + + struct RefMutex(&'static Mutex); + impl RefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&Mutex`, we can't get to `&mut Mutex` no matter what `self` is + refself.0.lock().unwrap(); + refmutself.0.lock().unwrap(); + self.0.lock().unwrap(); + } + } + + struct ArcMutex(Arc>); + impl ArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &Mutex`, we can't get a `&mut Mutex` no matter what `self` is + refself.0.lock().unwrap(); + refmutself.0.lock().unwrap(); + self.0.lock().unwrap(); + } + } + + struct RefMutMutex(&'static mut Mutex); + impl RefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut Mutex`, we _can_ get a `&mut Mutex` if we have `self`/`&mut self` + refself.0.lock().unwrap(); + refmutself.0.lock().unwrap(); + //~^ mut_mutex_lock + self.0.lock().unwrap(); + //~^ mut_mutex_lock + } + } + + struct ValueMutex(Mutex); + impl ValueMutex { + fn foo(mut self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Mutex`, we _can_ get a `&mut Mutex` if we have `self`/`&mut self` + refself.0.lock().unwrap(); + refmutself.0.lock().unwrap(); + //~^ mut_mutex_lock + self.0.lock().unwrap(); + //~^ mut_mutex_lock + } + } + + struct RefRefMutex(&'static RefMutex); + impl RefRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&RefMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcRefMutex(Arc); + impl ArcRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &RefMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutRefMutex(&'static mut RefMutex); + impl RefMutRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut RefMutex = &mut &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ValueRefMutex(RefMutex); + impl ValueRefMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `RefMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefArcMutex(&'static ArcMutex); + impl RefArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &RefMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcArcMutex(Arc); + impl ArcArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &ArcMutex = &&Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutArcMutex(&'static mut ArcMutex); + impl RefMutArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut ArcMutex = &mut &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ValueArcMutex(ArcMutex); + impl ValueArcMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `ArcMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefRefMutMutex(&'static RefMutMutex); + impl RefRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&RefMutMutex = &&mut Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcRefMutMutex(Arc); + impl ArcRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &RefMutMutex = &&mut Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutRefMutMutex(&'static mut RefMutMutex); + impl RefMutRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut RefMutMutex = &mut &mut Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + //~^ mut_mutex_lock + self.0.0.lock().unwrap(); + //~^ mut_mutex_lock + } + } + + struct ValueRefMutMutex(RefMutMutex); + impl ValueRefMutMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `RefMutMutex = &mut Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + //~^ mut_mutex_lock + self.0.0.lock().unwrap(); + //~^ mut_mutex_lock + } + } + + struct RefValueMutex(&'static ValueMutex); + impl RefValueMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&ValueMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct ArcValueMutex(Arc); + impl ArcValueMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `Arc = &ValueMutex = &Mutex`, + // we can't get to `&mut Mutex` no matter what `self` is + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + self.0.0.lock().unwrap(); + } + } + + struct RefMutValueMutex(&'static mut ValueMutex); + impl RefMutValueMutex { + fn foo(self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `&mut ValueMutex = &mut Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + //~^ mut_mutex_lock + self.0.0.lock().unwrap(); + //~^ mut_mutex_lock + } + } + + struct ValueValueMutex(ValueMutex); + impl ValueValueMutex { + fn foo(mut self, refself: &Self, refmutself: &mut Self) { + // since `.0` is `ValueMutex = Mutex`, + // we _can_ get to `&mut Mutex` if we have `self`/`&mut self` + refself.0.0.lock().unwrap(); + refmutself.0.0.lock().unwrap(); + //~^ mut_mutex_lock + self.0.0.lock().unwrap(); + //~^ mut_mutex_lock + } + } + + fn index(mutexes: &mut [Mutex]) { + // even though `[0]` is _currently_ an `.index(0)`, it can be turned into `.index_mut()` to + // enable mutable access: `&mut [Mutex] -> &mut Mutex` + mutexes[0].lock().unwrap(); + //~^ mut_mutex_lock + + // `exes` is `&[Mutex] = &Mutex`, so we can't get to `&mut Mutex` no matter what + let exes: &_ = mutexes; + exes[0].lock().unwrap(); + } +} + fn main() {} diff --git a/tests/ui/mut_mutex_lock.stderr b/tests/ui/mut_mutex_lock.stderr index 587405449523..e127050ad2f7 100644 --- a/tests/ui/mut_mutex_lock.stderr +++ b/tests/ui/mut_mutex_lock.stderr @@ -13,5 +13,83 @@ error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) ref LL | let mut value = mut_ref_mut_ref_mutex.lock().unwrap(); | ^^^^ help: change this to: `get_mut` -error: aborting due to 2 previous errors +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:68:26 + | +LL | refmutself.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:70:20 + | +LL | self.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:80:26 + | +LL | refmutself.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:82:20 + | +LL | self.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:203:28 + | +LL | refmutself.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:205:22 + | +LL | self.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:216:28 + | +LL | refmutself.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:218:22 + | +LL | self.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:251:28 + | +LL | refmutself.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:253:22 + | +LL | self.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:264:28 + | +LL | refmutself.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:266:22 + | +LL | self.0.0.lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference + --> tests/ui/mut_mutex_lock.rs:274:20 + | +LL | mutexes[0].lock().unwrap(); + | ^^^^ help: change this to: `get_mut` + +error: aborting due to 15 previous errors From 640be36ff903f61903a24c01d6ac3a6018d68d09 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 18 Dec 2025 22:31:01 +0100 Subject: [PATCH 3/9] Jarcho's suggestion --- clippy_lints/src/methods/mut_mutex_lock.rs | 100 +++++++++++---------- tests/ui/mut_mutex_lock.fixed | 39 ++++++++ tests/ui/mut_mutex_lock.rs | 39 ++++++++ 3 files changed, 132 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 19e5356deb2c..667d6e902178 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -1,58 +1,66 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::expr_custom_deref_adjustment; use clippy_utils::res::MaybeDef; -use clippy_utils::ty::peel_and_count_ty_refs; +use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Mutability}; +use rustc_hir::{Expr, ExprKind, Mutability, UnOp}; use rustc_lint::LateContext; +use rustc_middle::ty::adjustment::Adjust; use rustc_span::{Span, sym}; use super::MUT_MUTEX_LOCK; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_span: Span) { - // given a `recv` like `a.b.mutex`, this returns `[a.b.mutex, a.b, a]` - let mut projection_chain = std::iter::successors(Some(recv), |recv| { - if let ExprKind::Index(r, ..) | ExprKind::Field(r, _) = recv.kind { - Some(r) - } else { - None - } - }); + let typeck = cx.typeck_results(); + if !typeck.expr_ty_adjusted(recv).peel_refs().is_diag_item(cx, sym::Mutex) { + return; + } - if (cx.typeck_results().expr_ty_adjusted(recv)) - .peel_refs() - .is_diag_item(cx, sym::Mutex) - // If, somewhere along the projection chain, we stumble upon a field of type `&T`, or dereference a - // type like `Arc` to `&T`, we no longer have mutable access to the undelying `Mutex` - && projection_chain.all(|recv| { - let expr_ty = cx.typeck_results().expr_ty(recv); - // The reason we don't use `expr_ty_adjusted` here is twofold: - // - // Consider code like this: - // ```rs - // struct Foo(Mutex); - // - // fn fun(f: &Foo) { - // f.0.lock() - // } - // ``` - // - In the outermost receiver (`f.0`), the adjusted type would be `&Mutex`, due to an adjustment - // performed by `Mutex::lock`. - // - In the intermediary receivers (here, only `f`), the adjusted type would be fully dereferenced - // (`Foo`), which would make us miss the fact that `f` is actually behind a `&` -- this - // information is preserved in the pre-adjustment type (`&Foo`) - peel_and_count_ty_refs(expr_ty).2 != Some(Mutability::Not) - && expr_custom_deref_adjustment(cx, recv) != Some(Mutability::Not) - }) - { - span_lint_and_sugg( - cx, - MUT_MUTEX_LOCK, - name_span, - "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference", - "change this to", - "get_mut".to_owned(), - Applicability::MaybeIncorrect, - ); + let deref_mut_trait = cx.tcx.lang_items().deref_mut_trait(); + let index_mut_trait = cx.tcx.lang_items().index_mut_trait(); + let impls_deref_mut = |ty| deref_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[])); + let impls_index_mut = |ty, idx| index_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[idx])); + let mut r = recv; + 'outer: loop { + if !(typeck.expr_adjustments(r)) + .iter() + .map_while(|a| match a.kind { + Adjust::Deref(x) => Some((a.target, x)), + _ => None, + }) + .try_fold(typeck.expr_ty(r), |ty, (target, deref)| match deref { + None => (ty.ref_mutability() != Some(Mutability::Not)).then_some(target), + Some(_) => impls_deref_mut(ty).then_some(target), + }) + .is_some() + { + return; + } + loop { + match r.kind { + ExprKind::Field(base, _) => r = base, + ExprKind::Index(base, idx, _) + if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) => + { + r = base; + }, + // `base` here can't actually have adjustments + ExprKind::Unary(UnOp::Deref, base) if impls_deref_mut(typeck.expr_ty_adjusted(base)) => { + r = base; + continue; + }, + _ => break 'outer, + } + continue 'outer; + } } + + span_lint_and_sugg( + cx, + MUT_MUTEX_LOCK, + name_span, + "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference", + "change this to", + "get_mut".to_owned(), + Applicability::MaybeIncorrect, + ); } diff --git a/tests/ui/mut_mutex_lock.fixed b/tests/ui/mut_mutex_lock.fixed index b81fc5544532..cdb2cc7538e5 100644 --- a/tests/ui/mut_mutex_lock.fixed +++ b/tests/ui/mut_mutex_lock.fixed @@ -278,6 +278,45 @@ mod issue16253 { let exes: &_ = mutexes; exes[0].lock().unwrap(); } + + mod deref_but_not_deref_mut { + use super::*; + + struct Foo(Mutex); + + impl std::ops::Deref for Foo { + type Target = Mutex; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + fn main(f: &mut Foo) { + // This can't be changed to use `get_mut`, as `Foo: DerefMut>` doesn't hold + f.lock().unwrap(); + } + } + + mod index_but_not_index_mut { + use super::*; + + struct Foo(Mutex); + + impl std::ops::Index for Foo { + type Output = Mutex; + + fn index(&self, _: usize) -> &Self::Output { + &self.0 + } + } + + fn main(f: &mut Foo) { + // This can't be changed to use `index_mut`, as `Foo: IndexMut>` doesn't + // hold + f[0].lock().unwrap(); + } + } } fn main() {} diff --git a/tests/ui/mut_mutex_lock.rs b/tests/ui/mut_mutex_lock.rs index 521dab9560ac..55a287f65cf5 100644 --- a/tests/ui/mut_mutex_lock.rs +++ b/tests/ui/mut_mutex_lock.rs @@ -278,6 +278,45 @@ mod issue16253 { let exes: &_ = mutexes; exes[0].lock().unwrap(); } + + mod deref_but_not_deref_mut { + use super::*; + + struct Foo(Mutex); + + impl std::ops::Deref for Foo { + type Target = Mutex; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + fn main(f: &mut Foo) { + // This can't be changed to use `get_mut`, as `Foo: DerefMut>` doesn't hold + f.lock().unwrap(); + } + } + + mod index_but_not_index_mut { + use super::*; + + struct Foo(Mutex); + + impl std::ops::Index for Foo { + type Output = Mutex; + + fn index(&self, _: usize) -> &Self::Output { + &self.0 + } + } + + fn main(f: &mut Foo) { + // This can't be changed to use `index_mut`, as `Foo: IndexMut>` doesn't + // hold + f[0].lock().unwrap(); + } + } } fn main() {} From 759ee184287d985b7d6a8e1f6c91a1bbff6ce94c Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 19 Dec 2025 13:32:40 +0100 Subject: [PATCH 4/9] fix: _return_ when doesn't impl {index/deref}_mut --- clippy_lints/src/methods/mut_mutex_lock.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 667d6e902178..564bfcce22e3 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -38,15 +38,21 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s loop { match r.kind { ExprKind::Field(base, _) => r = base, - ExprKind::Index(base, idx, _) - if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) => - { - r = base; + ExprKind::Index(base, idx, _) => { + if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) { + r = base; + } else { + return; + } }, - // `base` here can't actually have adjustments - ExprKind::Unary(UnOp::Deref, base) if impls_deref_mut(typeck.expr_ty_adjusted(base)) => { - r = base; - continue; + ExprKind::Unary(UnOp::Deref, base) => { + if impls_deref_mut(typeck.expr_ty_adjusted(base)) { + r = base; + // `base` here can't actually have adjustments + continue; + } else { + return; + } }, _ => break 'outer, } From d72a72573ad30f5eaab7995f9a4d72de2afebcb8 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 19 Dec 2025 13:33:51 +0100 Subject: [PATCH 5/9] clippy, simplify --- clippy_lints/src/methods/mut_mutex_lock.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 564bfcce22e3..6e6753a785d8 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -21,17 +21,17 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s let impls_index_mut = |ty, idx| index_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[idx])); let mut r = recv; 'outer: loop { - if !(typeck.expr_adjustments(r)) + if (typeck.expr_adjustments(r)) .iter() .map_while(|a| match a.kind { Adjust::Deref(x) => Some((a.target, x)), _ => None, }) .try_fold(typeck.expr_ty(r), |ty, (target, deref)| match deref { - None => (ty.ref_mutability() != Some(Mutability::Not)).then_some(target), Some(_) => impls_deref_mut(ty).then_some(target), + None => (ty.ref_mutability() != Some(Mutability::Not)).then_some(target), }) - .is_some() + .is_none() { return; } From 57b8d0dade5ec5bc131e66c01fd0d65729fec8d3 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 19 Dec 2025 14:03:35 +0100 Subject: [PATCH 6/9] remove optimization for simpler code since there won't be any adjustments after an explicit deref, the adjustment checking step should finish pretty fast --- clippy_lints/src/methods/mut_mutex_lock.rs | 41 ++++++++++------------ 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 6e6753a785d8..170c7041e154 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -20,7 +20,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s let impls_deref_mut = |ty| deref_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[])); let impls_index_mut = |ty, idx| index_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[idx])); let mut r = recv; - 'outer: loop { + loop { if (typeck.expr_adjustments(r)) .iter() .map_while(|a| match a.kind { @@ -35,28 +35,23 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s { return; } - loop { - match r.kind { - ExprKind::Field(base, _) => r = base, - ExprKind::Index(base, idx, _) => { - if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) { - r = base; - } else { - return; - } - }, - ExprKind::Unary(UnOp::Deref, base) => { - if impls_deref_mut(typeck.expr_ty_adjusted(base)) { - r = base; - // `base` here can't actually have adjustments - continue; - } else { - return; - } - }, - _ => break 'outer, - } - continue 'outer; + match r.kind { + ExprKind::Field(base, _) => r = base, + ExprKind::Index(base, idx, _) => { + if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) { + r = base; + } else { + return; + } + }, + ExprKind::Unary(UnOp::Deref, base) => { + if impls_deref_mut(typeck.expr_ty_adjusted(base)) { + r = base; + } else { + return; + } + }, + _ => break, } } From e6755c5b5341f9133397eb1a0adfcadb881385cf Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 19 Dec 2025 14:01:55 +0100 Subject: [PATCH 7/9] document --- clippy_lints/src/methods/mut_mutex_lock.rs | 33 ++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 170c7041e154..201fd9c7fced 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -19,8 +19,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s let index_mut_trait = cx.tcx.lang_items().index_mut_trait(); let impls_deref_mut = |ty| deref_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[])); let impls_index_mut = |ty, idx| index_mut_trait.is_some_and(|trait_id| implements_trait(cx, ty, trait_id, &[idx])); + + // The mutex was accessed either directly (`mutex.lock()`), or through a series of + // deref/field/indexing projections. Since the final `.lock()` call only requires `&Mutex`, + // those might be immutable, and so we need to manually check whether mutable projections + // would've been possible. For that, we'll repeatedly peel off projections and check each + // intermediary receiver. let mut r = recv; loop { + // Check that the (deref) adjustments could be made mutable if (typeck.expr_adjustments(r)) .iter() .map_while(|a| match a.kind { @@ -28,29 +35,45 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s _ => None, }) .try_fold(typeck.expr_ty(r), |ty, (target, deref)| match deref { + // There has been an overloaded deref, most likely an immutable one, as `.lock()` didn't require a + // mutable one -- we need to check if a mutable deref would've been possible, i.e. if + // `ty: DerefMut` (we don't need to check the `Target` part, as `Deref` and `DerefMut` + // impls necessarily have the same one) Some(_) => impls_deref_mut(ty).then_some(target), + // There has been a simple deref; if it happened on a `&T`, then we know it will can't be changed to + // provide mutable access None => (ty.ref_mutability() != Some(Mutability::Not)).then_some(target), }) .is_none() { return; } + + // Peel off one projection match r.kind { - ExprKind::Field(base, _) => r = base, - ExprKind::Index(base, idx, _) => { - if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) { + // In order to be able to make this `*` mean `.deref_mut()`, `base: DerefMut` needs to hold + ExprKind::Unary(UnOp::Deref, base) => { + if impls_deref_mut(typeck.expr_ty_adjusted(base)) { r = base; } else { return; } }, - ExprKind::Unary(UnOp::Deref, base) => { - if impls_deref_mut(typeck.expr_ty_adjusted(base)) { + // In order to be able to make this `[idx]` mean `.index_mut(idx)`, `base: IndexMut` needs to hold + ExprKind::Index(base, idx, _) => { + // NOTE: the reason we do need to take into account `idx` here is that it's a _generic_ of + // `IndexMut`, not an associated type of the impl + if impls_index_mut(typeck.expr_ty_adjusted(base), typeck.expr_ty_adjusted(idx).into()) { r = base; } else { return; } }, + // A field projection by itself can't be mutable/immutable -- we'll only need to check + // that the field type is not a `&T`, and we'll do that in the next iteration of the + // loop, during adjustment checking + ExprKind::Field(base, _) => r = base, + // No more projections to check _ => break, } } From 1b4e626a52eba7fb734cb21570aee9957fa5d1b2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 19 Dec 2025 15:21:13 +0100 Subject: [PATCH 8/9] WIP: don't lint statics --- clippy_lints/src/methods/mut_mutex_lock.rs | 18 +++++++++++++-- tests/ui/mut_mutex_lock.fixed | 6 +++++ tests/ui/mut_mutex_lock.rs | 6 +++++ tests/ui/mut_mutex_lock.stderr | 26 +++++++++++----------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs index 201fd9c7fced..8af7e4abd663 100644 --- a/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/clippy_lints/src/methods/mut_mutex_lock.rs @@ -73,8 +73,22 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, name_s // that the field type is not a `&T`, and we'll do that in the next iteration of the // loop, during adjustment checking ExprKind::Field(base, _) => r = base, - // No more projections to check - _ => break, + // We arrived at the innermost receiver + _ => { + if let ExprKind::Path(ref p) = r.kind + && cx + .qpath_res(p, r.hir_id) + .opt_def_id() + .and_then(|id| cx.tcx.static_mutability(id)) + == Some(Mutability::Not) + { + // The mutex is stored in a `static`, and we don't want to suggest making that + // mutable + return; + } + // No more projections to check + break; + }, } } diff --git a/tests/ui/mut_mutex_lock.fixed b/tests/ui/mut_mutex_lock.fixed index cdb2cc7538e5..2ac50a1adf33 100644 --- a/tests/ui/mut_mutex_lock.fixed +++ b/tests/ui/mut_mutex_lock.fixed @@ -37,6 +37,12 @@ fn mut_ref_ref_mutex_lock() { *guard += 1; } +static MTX: Mutex = Mutex::new(0); + +fn dont_suggest_on_statics() { + MTX.lock().unwrap(); +} + mod issue16253 { use std::sync::{Arc, Mutex}; diff --git a/tests/ui/mut_mutex_lock.rs b/tests/ui/mut_mutex_lock.rs index 55a287f65cf5..6aaed16989f7 100644 --- a/tests/ui/mut_mutex_lock.rs +++ b/tests/ui/mut_mutex_lock.rs @@ -37,6 +37,12 @@ fn mut_ref_ref_mutex_lock() { *guard += 1; } +static MTX: Mutex = Mutex::new(0); + +fn dont_suggest_on_statics() { + MTX.lock().unwrap(); +} + mod issue16253 { use std::sync::{Arc, Mutex}; diff --git a/tests/ui/mut_mutex_lock.stderr b/tests/ui/mut_mutex_lock.stderr index e127050ad2f7..2e2f0072a811 100644 --- a/tests/ui/mut_mutex_lock.stderr +++ b/tests/ui/mut_mutex_lock.stderr @@ -14,79 +14,79 @@ LL | let mut value = mut_ref_mut_ref_mutex.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:68:26 + --> tests/ui/mut_mutex_lock.rs:74:26 | LL | refmutself.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:70:20 + --> tests/ui/mut_mutex_lock.rs:76:20 | LL | self.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:80:26 + --> tests/ui/mut_mutex_lock.rs:86:26 | LL | refmutself.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:82:20 + --> tests/ui/mut_mutex_lock.rs:88:20 | LL | self.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:203:28 + --> tests/ui/mut_mutex_lock.rs:209:28 | LL | refmutself.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:205:22 + --> tests/ui/mut_mutex_lock.rs:211:22 | LL | self.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:216:28 + --> tests/ui/mut_mutex_lock.rs:222:28 | LL | refmutself.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:218:22 + --> tests/ui/mut_mutex_lock.rs:224:22 | LL | self.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:251:28 + --> tests/ui/mut_mutex_lock.rs:257:28 | LL | refmutself.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:253:22 + --> tests/ui/mut_mutex_lock.rs:259:22 | LL | self.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:264:28 + --> tests/ui/mut_mutex_lock.rs:270:28 | LL | refmutself.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:266:22 + --> tests/ui/mut_mutex_lock.rs:272:22 | LL | self.0.0.lock().unwrap(); | ^^^^ help: change this to: `get_mut` error: calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference - --> tests/ui/mut_mutex_lock.rs:274:20 + --> tests/ui/mut_mutex_lock.rs:280:20 | LL | mutexes[0].lock().unwrap(); | ^^^^ help: change this to: `get_mut` From 37d8ef44ffc16c176bb599f7b174cda87676b699 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 19 Dec 2025 15:38:23 +0100 Subject: [PATCH 9/9] fix dogfood --- tests/ui/arc_with_non_send_sync.rs | 3 +- tests/ui/arc_with_non_send_sync.stderr | 6 +- tests/ui/await_holding_lock.rs | 4 +- .../branches_sharing_code/false_positives.rs | 2 +- tests/ui/entry.fixed | 3 +- tests/ui/entry.rs | 3 +- tests/ui/entry.stderr | 2 +- tests/ui/if_let_mutex.rs | 2 +- tests/ui/let_underscore_lock.rs | 1 + tests/ui/let_underscore_lock.stderr | 8 +-- tests/ui/redundant_locals.rs | 3 +- tests/ui/redundant_locals.stderr | 56 ++++++++--------- ...edundant_pattern_matching_drop_order.fixed | 1 + .../redundant_pattern_matching_drop_order.rs | 1 + ...dundant_pattern_matching_drop_order.stderr | 44 ++++++------- tests/ui/significant_drop_in_scrutinee.rs | 1 + tests/ui/significant_drop_in_scrutinee.stderr | 62 +++++++++---------- tests/ui/significant_drop_tightening.fixed | 1 + tests/ui/significant_drop_tightening.rs | 1 + tests/ui/significant_drop_tightening.stderr | 8 +-- tests/ui/swap_with_temporary.fixed | 1 + tests/ui/swap_with_temporary.rs | 1 + tests/ui/swap_with_temporary.stderr | 44 ++++++------- tests/ui/unnecessary_map_or.fixed | 11 ++-- tests/ui/unnecessary_map_or.rs | 11 ++-- tests/ui/unnecessary_map_or.stderr | 60 +++++++++--------- 26 files changed, 175 insertions(+), 165 deletions(-) diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs index 07025ccc42fd..10a8d6c34ed0 100644 --- a/tests/ui/arc_with_non_send_sync.rs +++ b/tests/ui/arc_with_non_send_sync.rs @@ -1,6 +1,5 @@ //@aux-build:proc_macros.rs #![warn(clippy::arc_with_non_send_sync)] -#![allow(unused_variables)] #[macro_use] extern crate proc_macros; @@ -35,7 +34,7 @@ fn main() { let _ = Arc::new(RefCell::new(42)); //~^ arc_with_non_send_sync - let mutex = Mutex::new(1); + let mutex = &Mutex::new(1); let _ = Arc::new(mutex.lock().unwrap()); //~^ arc_with_non_send_sync diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr index ce726206b0cd..1bacd836a1f2 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -1,5 +1,5 @@ error: usage of an `Arc` that is not `Send` and `Sync` - --> tests/ui/arc_with_non_send_sync.rs:35:13 + --> tests/ui/arc_with_non_send_sync.rs:34:13 | LL | let _ = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | let _ = Arc::new(RefCell::new(42)); = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]` error: usage of an `Arc` that is not `Send` and `Sync` - --> tests/ui/arc_with_non_send_sync.rs:39:13 + --> tests/ui/arc_with_non_send_sync.rs:38:13 | LL | let _ = Arc::new(mutex.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | let _ = Arc::new(mutex.lock().unwrap()); = help: otherwise make `MutexGuard<'_, i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex` error: usage of an `Arc` that is not `Send` and `Sync` - --> tests/ui/arc_with_non_send_sync.rs:42:13 + --> tests/ui/arc_with_non_send_sync.rs:41:13 | LL | let _ = Arc::new(&42 as *const i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/await_holding_lock.rs b/tests/ui/await_holding_lock.rs index cecf00c934fe..9d5dc1300301 100644 --- a/tests/ui/await_holding_lock.rs +++ b/tests/ui/await_holding_lock.rs @@ -173,7 +173,7 @@ async fn baz() -> u32 { 42 } -async fn no_await(x: std::sync::Mutex) { +async fn no_await(x: &std::sync::Mutex) { let mut guard = x.lock().unwrap(); *guard += 1; } @@ -182,7 +182,7 @@ async fn no_await(x: std::sync::Mutex) { // something the needs to be fixed in rustc. There's already drop-tracking, but this is currently // disabled, see rust-lang/rust#93751. This case isn't picked up by drop-tracking though. If the // `*guard += 1` is removed it is picked up. -async fn dropped_before_await(x: std::sync::Mutex) { +async fn dropped_before_await(x: &std::sync::Mutex) { let mut guard = x.lock().unwrap(); //~^ ERROR: this `MutexGuard` is held across an await point *guard += 1; diff --git a/tests/ui/branches_sharing_code/false_positives.rs b/tests/ui/branches_sharing_code/false_positives.rs index 49496e631fb1..44a6786a1e5b 100644 --- a/tests/ui/branches_sharing_code/false_positives.rs +++ b/tests/ui/branches_sharing_code/false_positives.rs @@ -1,6 +1,6 @@ //@ check-pass -#![allow(dead_code)] +#![allow(clippy::mut_mutex_lock)] #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)] use std::sync::Mutex; diff --git a/tests/ui/entry.fixed b/tests/ui/entry.fixed index 75e173b9a84d..e9b360052715 100644 --- a/tests/ui/entry.fixed +++ b/tests/ui/entry.fixed @@ -255,8 +255,7 @@ mod issue_16173 { async fn f() {} - async fn foo() { - let mu_map = Mutex::new(HashMap::new()); + async fn foo(mu_map: &Mutex>) { if !mu_map.lock().unwrap().contains_key(&0) { f().await; mu_map.lock().unwrap().insert(0, 0); diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 7e3308c87356..9d3bfef55880 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -261,8 +261,7 @@ mod issue_16173 { async fn f() {} - async fn foo() { - let mu_map = Mutex::new(HashMap::new()); + async fn foo(mu_map: &Mutex>) { if !mu_map.lock().unwrap().contains_key(&0) { f().await; mu_map.lock().unwrap().insert(0, 0); diff --git a/tests/ui/entry.stderr b/tests/ui/entry.stderr index 4a29b3860e89..6170dd5bcbb0 100644 --- a/tests/ui/entry.stderr +++ b/tests/ui/entry.stderr @@ -247,7 +247,7 @@ LL + } | error: usage of `contains_key` followed by `insert` on a `HashMap` - --> tests/ui/entry.rs:285:5 + --> tests/ui/entry.rs:284:5 | LL | / if !m.contains_key(&k) { LL | | diff --git a/tests/ui/if_let_mutex.rs b/tests/ui/if_let_mutex.rs index 72058ea33ee7..4f878cf9ebf1 100644 --- a/tests/ui/if_let_mutex.rs +++ b/tests/ui/if_let_mutex.rs @@ -5,7 +5,7 @@ //@[edition2024] edition:2024 //@[edition2024] check-pass #![warn(clippy::if_let_mutex)] -#![allow(clippy::redundant_pattern_matching)] +#![allow(clippy::redundant_pattern_matching, clippy::mut_mutex_lock)] use std::ops::Deref; use std::sync::Mutex; diff --git a/tests/ui/let_underscore_lock.rs b/tests/ui/let_underscore_lock.rs index 28d8dd498319..3220a60c8e42 100644 --- a/tests/ui/let_underscore_lock.rs +++ b/tests/ui/let_underscore_lock.rs @@ -1,4 +1,5 @@ #![warn(clippy::let_underscore_lock)] +#![allow(clippy::mut_mutex_lock)] extern crate parking_lot; diff --git a/tests/ui/let_underscore_lock.stderr b/tests/ui/let_underscore_lock.stderr index a38309dd4fab..1a56360023a2 100644 --- a/tests/ui/let_underscore_lock.stderr +++ b/tests/ui/let_underscore_lock.stderr @@ -1,5 +1,5 @@ error: non-binding `let` on a synchronization lock - --> tests/ui/let_underscore_lock.rs:10:5 + --> tests/ui/let_underscore_lock.rs:11:5 | LL | let _ = p_m.lock(); | ^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | let _ = p_m.lock(); = help: to override `-D warnings` add `#[allow(clippy::let_underscore_lock)]` error: non-binding `let` on a synchronization lock - --> tests/ui/let_underscore_lock.rs:14:5 + --> tests/ui/let_underscore_lock.rs:15:5 | LL | let _ = p_m1.lock(); | ^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let _ = p_m1.lock(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding `let` on a synchronization lock - --> tests/ui/let_underscore_lock.rs:18:5 + --> tests/ui/let_underscore_lock.rs:19:5 | LL | let _ = p_rw.read(); | ^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = p_rw.read(); = help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop` error: non-binding `let` on a synchronization lock - --> tests/ui/let_underscore_lock.rs:20:5 + --> tests/ui/let_underscore_lock.rs:21:5 | LL | let _ = p_rw.write(); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_locals.rs b/tests/ui/redundant_locals.rs index b66532dd22ee..49a673439c21 100644 --- a/tests/ui/redundant_locals.rs +++ b/tests/ui/redundant_locals.rs @@ -1,9 +1,8 @@ //@aux-build:proc_macros.rs -#![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)] +#![allow(clippy::mut_mutex_lock, clippy::no_effect, clippy::needless_pass_by_ref_mut)] #![warn(clippy::redundant_locals)] #![feature(coroutines, stmt_expr_attributes)] -extern crate proc_macros; use proc_macros::{external, with_span}; fn main() {} diff --git a/tests/ui/redundant_locals.stderr b/tests/ui/redundant_locals.stderr index ae3631cdf15f..7e01aca028d5 100644 --- a/tests/ui/redundant_locals.stderr +++ b/tests/ui/redundant_locals.stderr @@ -1,11 +1,11 @@ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:13:5 + --> tests/ui/redundant_locals.rs:12:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:12:9 + --> tests/ui/redundant_locals.rs:11:9 | LL | let x = 1; | ^ @@ -13,157 +13,157 @@ LL | let x = 1; = help: to override `-D warnings` add `#[allow(clippy::redundant_locals)]` error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:19:5 + --> tests/ui/redundant_locals.rs:18:5 | LL | let mut x = x; | ^^^^^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:18:9 + --> tests/ui/redundant_locals.rs:17:9 | LL | let mut x = 1; | ^^^^^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:50:5 + --> tests/ui/redundant_locals.rs:49:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:49:14 + --> tests/ui/redundant_locals.rs:48:14 | LL | fn parameter(x: i32) { | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:56:5 + --> tests/ui/redundant_locals.rs:55:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:55:9 + --> tests/ui/redundant_locals.rs:54:9 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:58:5 + --> tests/ui/redundant_locals.rs:57:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:56:9 + --> tests/ui/redundant_locals.rs:55:9 | LL | let x = x; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:60:5 + --> tests/ui/redundant_locals.rs:59:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:58:9 + --> tests/ui/redundant_locals.rs:57:9 | LL | let x = x; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:62:5 + --> tests/ui/redundant_locals.rs:61:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:60:9 + --> tests/ui/redundant_locals.rs:59:9 | LL | let x = x; | ^ error: redundant redefinition of a binding `a` - --> tests/ui/redundant_locals.rs:69:5 + --> tests/ui/redundant_locals.rs:68:5 | LL | let a = a; | ^^^^^^^^^^ | help: `a` is initially defined here - --> tests/ui/redundant_locals.rs:67:9 + --> tests/ui/redundant_locals.rs:66:9 | LL | let a = 1; | ^ error: redundant redefinition of a binding `b` - --> tests/ui/redundant_locals.rs:71:5 + --> tests/ui/redundant_locals.rs:70:5 | LL | let b = b; | ^^^^^^^^^^ | help: `b` is initially defined here - --> tests/ui/redundant_locals.rs:68:9 + --> tests/ui/redundant_locals.rs:67:9 | LL | let b = 2; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:78:9 + --> tests/ui/redundant_locals.rs:77:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:77:13 + --> tests/ui/redundant_locals.rs:76:13 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:86:9 + --> tests/ui/redundant_locals.rs:85:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:85:13 + --> tests/ui/redundant_locals.rs:84:13 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:90:9 + --> tests/ui/redundant_locals.rs:89:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:89:6 + --> tests/ui/redundant_locals.rs:88:6 | LL | |x: i32| { | ^ error: redundant redefinition of a binding `x` - --> tests/ui/redundant_locals.rs:110:9 + --> tests/ui/redundant_locals.rs:109:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> tests/ui/redundant_locals.rs:107:9 + --> tests/ui/redundant_locals.rs:106:9 | LL | let x = 1; | ^ error: redundant redefinition of a binding `a` - --> tests/ui/redundant_locals.rs:166:5 + --> tests/ui/redundant_locals.rs:165:5 | LL | let a = a; | ^^^^^^^^^^ | help: `a` is initially defined here - --> tests/ui/redundant_locals.rs:164:9 + --> tests/ui/redundant_locals.rs:163:9 | LL | let a = WithoutDrop(1); | ^ diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed index 490948442e11..25c3c5be8a0e 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.fixed +++ b/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -3,6 +3,7 @@ #![allow( clippy::if_same_then_else, clippy::equatable_if_let, + clippy::mut_mutex_lock, clippy::needless_ifs, clippy::needless_else )] diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs index d40fe84693b0..09bb1fedf52f 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.rs +++ b/tests/ui/redundant_pattern_matching_drop_order.rs @@ -3,6 +3,7 @@ #![allow( clippy::if_same_then_else, clippy::equatable_if_let, + clippy::mut_mutex_lock, clippy::needless_ifs, clippy::needless_else )] diff --git a/tests/ui/redundant_pattern_matching_drop_order.stderr b/tests/ui/redundant_pattern_matching_drop_order.stderr index 74462f022f70..ce126aa83840 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.stderr +++ b/tests/ui/redundant_pattern_matching_drop_order.stderr @@ -1,5 +1,5 @@ error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:15:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:16:12 | LL | if let Ok(_) = m.lock() {} | -------^^^^^----------- help: try: `if m.lock().is_ok()` @@ -10,7 +10,7 @@ LL | if let Ok(_) = m.lock() {} = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:17:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:18:12 | LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} | -------^^^^^^------------------------------------ help: try: `if Err::<(), _>(m.lock().unwrap().0).is_err()` @@ -19,7 +19,7 @@ LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:21:16 + --> tests/ui/redundant_pattern_matching_drop_order.rs:22:16 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -28,7 +28,7 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:24:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:25:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` @@ -37,31 +37,31 @@ LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:28:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:29:12 | LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {} | -------^^^^^----------------------------------------- help: try: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:30:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:31:12 | LL | if let Err(_) = Err::, _>(()) {} | -------^^^^^^------------------------------------------ help: try: `if Err::, _>(()).is_err()` error: redundant pattern matching, consider using `is_ok()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:33:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:34:12 | LL | if let Ok(_) = Ok::<_, ()>(String::new()) {} | -------^^^^^----------------------------- help: try: `if Ok::<_, ()>(String::new()).is_ok()` error: redundant pattern matching, consider using `is_err()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:35:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:36:12 | LL | if let Err(_) = Err::<(), _>((String::new(), ())) {} | -------^^^^^^------------------------------------ help: try: `if Err::<(), _>((String::new(), ())).is_err()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:39:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:40:12 | LL | if let Some(_) = Some(m.lock()) {} | -------^^^^^^^----------------- help: try: `if Some(m.lock()).is_some()` @@ -70,7 +70,7 @@ LL | if let Some(_) = Some(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:41:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:42:12 | LL | if let Some(_) = Some(m.lock().unwrap().0) {} | -------^^^^^^^---------------------------- help: try: `if Some(m.lock().unwrap().0).is_some()` @@ -79,7 +79,7 @@ LL | if let Some(_) = Some(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:45:16 + --> tests/ui/redundant_pattern_matching_drop_order.rs:46:16 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try: `if None::>.is_none()` @@ -88,7 +88,7 @@ LL | if let None = None::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:48:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:49:12 | LL | if let None = None::> { | -------^^^^------------------------------------ help: try: `if None::>.is_none()` @@ -97,25 +97,25 @@ LL | if let None = None::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_none()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:53:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:54:12 | LL | if let None = None::> {} | -------^^^^------------------------------------ help: try: `if None::>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:56:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:57:12 | LL | if let Some(_) = Some(String::new()) {} | -------^^^^^^^---------------------- help: try: `if Some(String::new()).is_some()` error: redundant pattern matching, consider using `is_some()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:58:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:59:12 | LL | if let Some(_) = Some((String::new(), ())) {} | -------^^^^^^^---------------------------- help: try: `if Some((String::new(), ())).is_some()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:62:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:63:12 | LL | if let Ready(_) = Ready(m.lock()) {} | -------^^^^^^^^------------------ help: try: `if Ready(m.lock()).is_ready()` @@ -124,7 +124,7 @@ LL | if let Ready(_) = Ready(m.lock()) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:64:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:65:12 | LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} | -------^^^^^^^^----------------------------- help: try: `if Ready(m.lock().unwrap().0).is_ready()` @@ -133,7 +133,7 @@ LL | if let Ready(_) = Ready(m.lock().unwrap().0) {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:68:16 + --> tests/ui/redundant_pattern_matching_drop_order.rs:69:16 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` @@ -142,7 +142,7 @@ LL | if let Pending = Pending::> {} = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:71:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:72:12 | LL | if let Pending = Pending::> { | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` @@ -151,19 +151,19 @@ LL | if let Pending = Pending::> { = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important error: redundant pattern matching, consider using `is_pending()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:76:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:77:12 | LL | if let Pending = Pending::> {} | -------^^^^^^^--------------------------------------- help: try: `if Pending::>.is_pending()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:79:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:80:12 | LL | if let Ready(_) = Ready(String::new()) {} | -------^^^^^^^^----------------------- help: try: `if Ready(String::new()).is_ready()` error: redundant pattern matching, consider using `is_ready()` - --> tests/ui/redundant_pattern_matching_drop_order.rs:81:12 + --> tests/ui/redundant_pattern_matching_drop_order.rs:82:12 | LL | if let Ready(_) = Ready((String::new(), ())) {} | -------^^^^^^^^----------------------------- help: try: `if Ready((String::new(), ())).is_ready()` diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index 78fc365bd5bb..5d84312b24f6 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -4,6 +4,7 @@ #![allow(dead_code, unused_assignments)] #![allow( clippy::match_single_binding, + clippy::mut_mutex_lock, clippy::single_match, clippy::uninlined_format_args, clippy::needless_lifetimes diff --git a/tests/ui/significant_drop_in_scrutinee.stderr b/tests/ui/significant_drop_in_scrutinee.stderr index b32b249fd429..8ba9f7234754 100644 --- a/tests/ui/significant_drop_in_scrutinee.stderr +++ b/tests/ui/significant_drop_in_scrutinee.stderr @@ -1,5 +1,5 @@ error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:60:11 + --> tests/ui/significant_drop_in_scrutinee.rs:61:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:147:11 + --> tests/ui/significant_drop_in_scrutinee.rs:148:11 | LL | match s.lock_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:169:11 + --> tests/ui/significant_drop_in_scrutinee.rs:170:11 | LL | match s.lock_m_m().get_the_value() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:218:11 + --> tests/ui/significant_drop_in_scrutinee.rs:219:11 | LL | match counter.temp_increment().len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:242:16 + --> tests/ui/significant_drop_in_scrutinee.rs:243:16 | LL | match (mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL ~ match (value, true) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:252:22 + --> tests/ui/significant_drop_in_scrutinee.rs:253:22 | LL | match (true, mutex1.lock().unwrap().s.len(), true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL ~ match (true, value, true) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:263:16 + --> tests/ui/significant_drop_in_scrutinee.rs:264:16 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL ~ match (value, true, mutex2.lock().unwrap().s.len()) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:263:54 + --> tests/ui/significant_drop_in_scrutinee.rs:264:54 | LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL ~ match (mutex1.lock().unwrap().s.len(), true, value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:316:11 + --> tests/ui/significant_drop_in_scrutinee.rs:317:11 | LL | match mutex.lock().unwrap().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +179,7 @@ LL ~ match value > 1 { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:324:15 + --> tests/ui/significant_drop_in_scrutinee.rs:325:15 | LL | match 1 < mutex.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -198,7 +198,7 @@ LL ~ match 1 < value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:343:11 + --> tests/ui/significant_drop_in_scrutinee.rs:344:11 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ LL ~ match value < mutex2.lock().unwrap().s.len() { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:343:44 + --> tests/ui/significant_drop_in_scrutinee.rs:344:44 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +240,7 @@ LL ~ match mutex1.lock().unwrap().s.len() < value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:356:11 + --> tests/ui/significant_drop_in_scrutinee.rs:357:11 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -261,7 +261,7 @@ LL ~ match value >= mutex2.lock().unwrap().s.len() { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:356:45 + --> tests/ui/significant_drop_in_scrutinee.rs:357:45 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -282,7 +282,7 @@ LL ~ match mutex1.lock().unwrap().s.len() >= value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:393:11 + --> tests/ui/significant_drop_in_scrutinee.rs:394:11 | LL | match get_mutex_guard().s.len() > 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL ~ match value > 1 { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:411:11 + --> tests/ui/significant_drop_in_scrutinee.rs:412:11 | LL | match match i { | ___________^ @@ -333,7 +333,7 @@ LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:438:11 + --> tests/ui/significant_drop_in_scrutinee.rs:439:11 | LL | match if i > 1 { | ___________^ @@ -366,7 +366,7 @@ LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:493:11 + --> tests/ui/significant_drop_in_scrutinee.rs:494:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -384,7 +384,7 @@ LL ~ match (&value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:542:11 + --> tests/ui/significant_drop_in_scrutinee.rs:543:11 | LL | match mutex.lock().unwrap().i = i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -403,7 +403,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:549:15 + --> tests/ui/significant_drop_in_scrutinee.rs:550:15 | LL | match i = mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -422,7 +422,7 @@ LL ~ match i = value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:556:11 + --> tests/ui/significant_drop_in_scrutinee.rs:557:11 | LL | match mutex.lock().unwrap().i += 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -441,7 +441,7 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:563:16 + --> tests/ui/significant_drop_in_scrutinee.rs:564:16 | LL | match i += mutex.lock().unwrap().i { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -460,7 +460,7 @@ LL ~ match i += value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:627:11 + --> tests/ui/significant_drop_in_scrutinee.rs:628:11 | LL | match rwlock.read().unwrap().to_number() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -476,7 +476,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:654:11 + --> tests/ui/significant_drop_in_scrutinee.rs:655:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -492,7 +492,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:716:11 + --> tests/ui/significant_drop_in_scrutinee.rs:717:11 | LL | match guard.take().len() { | ^^^^^^^^^^^^^^^^^^ @@ -508,7 +508,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression - --> tests/ui/significant_drop_in_scrutinee.rs:741:16 + --> tests/ui/significant_drop_in_scrutinee.rs:742:16 | LL | for val in mutex.lock().unwrap().copy_old_lifetime() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -524,7 +524,7 @@ LL ~ for val in value { | error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression - --> tests/ui/significant_drop_in_scrutinee.rs:780:17 + --> tests/ui/significant_drop_in_scrutinee.rs:781:17 | LL | for val in [mutex.lock().unwrap()[0], 2] { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -540,7 +540,7 @@ LL ~ for val in [value, 2] { | error: temporary with significant `Drop` in `if let` scrutinee will live until the end of the `if let` expression - --> tests/ui/significant_drop_in_scrutinee.rs:789:24 + --> tests/ui/significant_drop_in_scrutinee.rs:790:24 | LL | if let Some(val) = mutex.lock().unwrap().first().copied() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -556,7 +556,7 @@ LL ~ if let Some(val) = value { | error: temporary with significant `Drop` in `while let` scrutinee will live until the end of the `while let` expression - --> tests/ui/significant_drop_in_scrutinee.rs:804:27 + --> tests/ui/significant_drop_in_scrutinee.rs:805:27 | LL | while let Some(val) = mutex.lock().unwrap().pop() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -567,7 +567,7 @@ LL | } = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:815:11 + --> tests/ui/significant_drop_in_scrutinee.rs:816:11 | LL | match *foo_async(&mutex).await.unwrap() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -583,7 +583,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:835:19 + --> tests/ui/significant_drop_in_scrutinee.rs:836:19 | LL | let _ = match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index 3d416056226c..2578944073de 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -1,4 +1,5 @@ #![warn(clippy::significant_drop_tightening)] +#![allow(clippy::mut_mutex_lock)] use std::sync::Mutex; diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index d9c4ad543593..56958e6e6a46 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -1,4 +1,5 @@ #![warn(clippy::significant_drop_tightening)] +#![allow(clippy::mut_mutex_lock)] use std::sync::Mutex; diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index 25cd9da73a10..28abbdb412c4 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -1,5 +1,5 @@ error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:10:9 + --> tests/ui/significant_drop_tightening.rs:11:9 | LL | pub fn complex_return_triggers_the_lint() -> i32 { | __________________________________________________- @@ -23,7 +23,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:105:13 + --> tests/ui/significant_drop_tightening.rs:106:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -42,7 +42,7 @@ LL + drop(lock); | error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:127:13 + --> tests/ui/significant_drop_tightening.rs:128:13 | LL | / { LL | | let mutex = Mutex::new(1i32); @@ -63,7 +63,7 @@ LL ~ | error: temporary with significant `Drop` can be early dropped - --> tests/ui/significant_drop_tightening.rs:134:17 + --> tests/ui/significant_drop_tightening.rs:135:17 | LL | / { LL | | let mutex = Mutex::new(vec![1i32]); diff --git a/tests/ui/swap_with_temporary.fixed b/tests/ui/swap_with_temporary.fixed index 4b4b0d4aebd2..4fd077a23f31 100644 --- a/tests/ui/swap_with_temporary.fixed +++ b/tests/ui/swap_with_temporary.fixed @@ -1,4 +1,5 @@ #![warn(clippy::swap_with_temporary)] +#![allow(clippy::mut_mutex_lock)] use std::mem::swap; diff --git a/tests/ui/swap_with_temporary.rs b/tests/ui/swap_with_temporary.rs index 8e35e6144d99..691815c935e1 100644 --- a/tests/ui/swap_with_temporary.rs +++ b/tests/ui/swap_with_temporary.rs @@ -1,4 +1,5 @@ #![warn(clippy::swap_with_temporary)] +#![allow(clippy::mut_mutex_lock)] use std::mem::swap; diff --git a/tests/ui/swap_with_temporary.stderr b/tests/ui/swap_with_temporary.stderr index 5ca4fccd37a2..3f617a68b893 100644 --- a/tests/ui/swap_with_temporary.stderr +++ b/tests/ui/swap_with_temporary.stderr @@ -1,11 +1,11 @@ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:22:5 + --> tests/ui/swap_with_temporary.rs:23:5 | LL | swap(&mut func(), &mut y); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `y = func()` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:22:15 + --> tests/ui/swap_with_temporary.rs:23:15 | LL | swap(&mut func(), &mut y); | ^^^^^^ @@ -13,121 +13,121 @@ LL | swap(&mut func(), &mut y); = help: to override `-D warnings` add `#[allow(clippy::swap_with_temporary)]` error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:25:5 + --> tests/ui/swap_with_temporary.rs:26:5 | LL | swap(&mut x, &mut func()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `x = func()` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:25:23 + --> tests/ui/swap_with_temporary.rs:26:23 | LL | swap(&mut x, &mut func()); | ^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:28:5 + --> tests/ui/swap_with_temporary.rs:29:5 | LL | swap(z, &mut func()); | ^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*z = func()` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:28:18 + --> tests/ui/swap_with_temporary.rs:29:18 | LL | swap(z, &mut func()); | ^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:36:5 + --> tests/ui/swap_with_temporary.rs:37:5 | LL | swap(&mut func(), z); | ^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*z = func()` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:36:15 + --> tests/ui/swap_with_temporary.rs:37:15 | LL | swap(&mut func(), z); | ^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:53:5 + --> tests/ui/swap_with_temporary.rs:54:5 | LL | swap(&mut mac!(funcall func), z); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*z = mac!(funcall func)` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:53:15 + --> tests/ui/swap_with_temporary.rs:54:15 | LL | swap(&mut mac!(funcall func), z); | ^^^^^^^^^^^^^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:55:5 + --> tests/ui/swap_with_temporary.rs:56:5 | LL | swap(&mut mac!(funcall func), mac!(ident z)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*mac!(ident z) = mac!(funcall func)` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:55:15 + --> tests/ui/swap_with_temporary.rs:56:15 | LL | swap(&mut mac!(funcall func), mac!(ident z)); | ^^^^^^^^^^^^^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:57:5 + --> tests/ui/swap_with_temporary.rs:58:5 | LL | swap(mac!(ident z), &mut mac!(funcall func)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*mac!(ident z) = mac!(funcall func)` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:57:30 + --> tests/ui/swap_with_temporary.rs:58:30 | LL | swap(mac!(ident z), &mut mac!(funcall func)); | ^^^^^^^^^^^^^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:59:5 + --> tests/ui/swap_with_temporary.rs:60:5 | LL | swap(mac!(refmut y), &mut func()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*mac!(refmut y) = func()` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:59:31 + --> tests/ui/swap_with_temporary.rs:60:31 | LL | swap(mac!(refmut y), &mut func()); | ^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:92:13 + --> tests/ui/swap_with_temporary.rs:93:13 | LL | swap(&mut vec![42], &mut self.thing.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*self.thing.lock().unwrap() = vec![42]` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:92:23 + --> tests/ui/swap_with_temporary.rs:93:23 | LL | swap(&mut vec![42], &mut self.thing.lock().unwrap()); | ^^^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:100:5 + --> tests/ui/swap_with_temporary.rs:101:5 | LL | swap(&mut ***v1, &mut vec![]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `***v1 = vec![]` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:100:27 + --> tests/ui/swap_with_temporary.rs:101:27 | LL | swap(&mut ***v1, &mut vec![]); | ^^^^^^ error: swapping with a temporary value is inefficient - --> tests/ui/swap_with_temporary.rs:118:5 + --> tests/ui/swap_with_temporary.rs:119:5 | LL | swap(&mut vec![], &mut v1.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `***v1.lock().unwrap() = vec![]` | note: this expression returns a temporary value - --> tests/ui/swap_with_temporary.rs:118:15 + --> tests/ui/swap_with_temporary.rs:119:15 | LL | swap(&mut vec![], &mut v1.lock().unwrap()); | ^^^^^^ diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index 10552431d65d..b3507125c0e3 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -1,9 +1,12 @@ //@aux-build:proc_macros.rs #![warn(clippy::unnecessary_map_or)] -#![allow(clippy::no_effect)] -#![allow(clippy::eq_op)] -#![allow(clippy::unnecessary_lazy_evaluations)] -#![allow(clippy::nonminimal_bool)] +#![allow( + clippy::no_effect, + clippy::eq_op, + clippy::unnecessary_lazy_evaluations, + clippy::mut_mutex_lock, + clippy::nonminimal_bool +)] #[clippy::msrv = "1.70.0"] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index 4b406ec2998b..eee0eabe7747 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -1,9 +1,12 @@ //@aux-build:proc_macros.rs #![warn(clippy::unnecessary_map_or)] -#![allow(clippy::no_effect)] -#![allow(clippy::eq_op)] -#![allow(clippy::unnecessary_lazy_evaluations)] -#![allow(clippy::nonminimal_bool)] +#![allow( + clippy::no_effect, + clippy::eq_op, + clippy::unnecessary_lazy_evaluations, + clippy::mut_mutex_lock, + clippy::nonminimal_bool +)] #[clippy::msrv = "1.70.0"] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index b8a22346c378..f634e98443cd 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -1,5 +1,5 @@ error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:13:13 + --> tests/ui/unnecessary_map_or.rs:16:13 | LL | let _ = Some(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + let _ = Some(5) == Some(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:15:13 + --> tests/ui/unnecessary_map_or.rs:18:13 | LL | let _ = Some(5).map_or(true, |n| n != 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + let _ = Some(5) != Some(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:17:13 + --> tests/ui/unnecessary_map_or.rs:20:13 | LL | let _ = Some(5).map_or(false, |n| { | _____________^ @@ -46,7 +46,7 @@ LL + let _ = Some(5) == Some(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:22:13 + --> tests/ui/unnecessary_map_or.rs:25:13 | LL | let _ = Some(5).map_or(false, |n| { | _____________^ @@ -63,7 +63,7 @@ LL + let _ = Some(5).is_some_and(|n| { | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:27:13 + --> tests/ui/unnecessary_map_or.rs:30:13 | LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL + let _ = Some(vec![5]).is_some_and(|n| n == [5]); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:29:13 + --> tests/ui/unnecessary_map_or.rs:32:13 | LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL + let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:31:13 + --> tests/ui/unnecessary_map_or.rs:34:13 | LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL + let _ = Some(5).is_some_and(|n| n == n); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:33:13 + --> tests/ui/unnecessary_map_or.rs:36:13 | LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL + let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:35:13 + --> tests/ui/unnecessary_map_or.rs:38:13 | LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -123,7 +123,7 @@ LL + let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:37:13 + --> tests/ui/unnecessary_map_or.rs:40:13 | LL | let _ = Ok::(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL + let _ = Ok::(5) == Ok(5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:39:13 + --> tests/ui/unnecessary_map_or.rs:42:13 | LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -147,7 +147,7 @@ LL + let _ = (Some(5) == Some(5)).then(|| 1); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:41:13 + --> tests/ui/unnecessary_map_or.rs:44:13 | LL | let _ = Some(5).map_or(true, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -159,7 +159,7 @@ LL + let _ = Some(5).is_none_or(|n| n == 5); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:43:13 + --> tests/ui/unnecessary_map_or.rs:46:13 | LL | let _ = Some(5).map_or(true, |n| 5 == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL + let _ = Some(5).is_none_or(|n| 5 == n); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:45:14 + --> tests/ui/unnecessary_map_or.rs:48:14 | LL | let _ = !Some(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -183,7 +183,7 @@ LL + let _ = !(Some(5) == Some(5)); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:47:13 + --> tests/ui/unnecessary_map_or.rs:50:13 | LL | let _ = Some(5).map_or(false, |n| n == 5) || false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -195,7 +195,7 @@ LL + let _ = (Some(5) == Some(5)) || false; | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:49:13 + --> tests/ui/unnecessary_map_or.rs:52:13 | LL | let _ = Some(5).map_or(false, |n| n == 5) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,7 +207,7 @@ LL + let _ = (Some(5) == Some(5)) as usize; | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:74:13 + --> tests/ui/unnecessary_map_or.rs:77:13 | LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ LL + let _ = r.is_ok_and(|x| x == 7); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:80:13 + --> tests/ui/unnecessary_map_or.rs:83:13 | LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ @@ -231,7 +231,7 @@ LL + let _ = r.is_ok_and(func); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:82:13 + --> tests/ui/unnecessary_map_or.rs:85:13 | LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -243,7 +243,7 @@ LL + let _ = Some(5).is_some_and(func); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:84:13 + --> tests/ui/unnecessary_map_or.rs:87:13 | LL | let _ = Some(5).map_or(true, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -255,7 +255,7 @@ LL + let _ = Some(5).is_none_or(func); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:90:13 + --> tests/ui/unnecessary_map_or.rs:93:13 | LL | let _ = r.map_or(false, |x| x == 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -267,7 +267,7 @@ LL + let _ = r == Ok(8); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:111:5 + --> tests/ui/unnecessary_map_or.rs:114:5 | LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL + o.is_none_or(|n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:111:34 + --> tests/ui/unnecessary_map_or.rs:114:34 | LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -291,7 +291,7 @@ LL + o.map_or(true, |n| n > 5) || (o as &Option).is_none_or(|n| n < 5) | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:126:5 + --> tests/ui/unnecessary_map_or.rs:129:5 | LL | o.map_or(true, |n| n > 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -303,7 +303,7 @@ LL + o.is_none_or(|n| n > 5) | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:131:13 + --> tests/ui/unnecessary_map_or.rs:134:13 | LL | let x = a.map_or(false, |a| a == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -315,7 +315,7 @@ LL + let x = a.is_some_and(|a| a == *s); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:133:13 + --> tests/ui/unnecessary_map_or.rs:136:13 | LL | let y = b.map_or(true, |b| b == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -327,7 +327,7 @@ LL + let y = b.is_none_or(|b| b == *s); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:139:13 + --> tests/ui/unnecessary_map_or.rs:142:13 | LL | assert!(Some("test").map_or(false, |x| x == "test")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -339,7 +339,7 @@ LL + assert!(Some("test") == Some("test")); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:143:13 + --> tests/ui/unnecessary_map_or.rs:146:13 | LL | assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -351,7 +351,7 @@ LL + assert!((Some("test") == Some("test")).then(|| 1).is_some()); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:160:9 + --> tests/ui/unnecessary_map_or.rs:163:9 | LL | _ = s.lock().unwrap().map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -363,7 +363,7 @@ LL + _ = s.lock().unwrap().is_some_and(|s| s == "foo"); | error: this `map_or` can be simplified - --> tests/ui/unnecessary_map_or.rs:164:9 + --> tests/ui/unnecessary_map_or.rs:167:9 | LL | _ = s.map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^