@@ -3,16 +3,32 @@ use clippy_utils::expr_custom_deref_adjustment;
33use clippy_utils:: res:: MaybeDef ;
44use clippy_utils:: ty:: peel_and_count_ty_refs;
55use rustc_errors:: Applicability ;
6- use rustc_hir:: { Expr , Mutability } ;
6+ use rustc_hir:: { Expr , ExprKind , Mutability } ;
77use rustc_lint:: LateContext ;
88use rustc_span:: { Span , sym} ;
99
1010use super :: MUT_MUTEX_LOCK ;
1111
1212pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , recv : & ' tcx Expr < ' tcx > , name_span : Span ) {
13- if matches ! ( expr_custom_deref_adjustment( cx, recv) , None | Some ( Mutability :: Mut ) )
14- // NOTE: the reason we don't use `expr_ty_adjusted` here is that a call to `Mutex::lock` by itself
15- // adjusts the receiver to be `&Mutex`
13+ // We don't want to lint on indexing and field accesses, as both of those would take exclusive
14+ // access to only part of a value -- which would conflict with any immutable reborrow over
15+ // the whole value
16+ if !matches ! ( recv. kind, ExprKind :: Field ( ..) | ExprKind :: Index ( ..) )
17+ // Make sure that we have a mutable access to `Mutex`:
18+ //
19+ // 1. Check that there are no custom deref adjustments turning the access immutable (e.g.
20+ // `Arc<Mutex>` derefs to `&Mutex`)
21+ // TODO: add tests for this
22+ && matches ! ( expr_custom_deref_adjustment( cx, recv) , None | Some ( Mutability :: Mut ) )
23+ // 2. Check that the receiver is behind one or more `&mut`s -- we want to have mutable
24+ // access, while not outright owning it -- if the latter were the case, then changing
25+ // `.lock()` to `.get_mut()`, could easily result in a conflict with other existing
26+ // immutable borrows.
27+ //
28+ // NOTE: `mutbl` being `Some` is enough to determine that there was at least one layer of
29+ // references, so no need to check `n`
30+ // NOTE: the reason we don't use `expr_ty_adjusted` here is that a call
31+ // to `Mutex::lock` by itself adjusts the receiver to be `&Mutex`
1632 && let ( recv_ty, _, Some ( Mutability :: Mut ) ) = peel_and_count_ty_refs ( cx. typeck_results ( ) . expr_ty ( recv) )
1733 && recv_ty. is_diag_item ( cx, sym:: Mutex )
1834 {
0 commit comments