1 //! Checks for uses of mutex where an atomic value could be used
3 //! This lint is **warn** by default
5 use clippy_utils
::diagnostics
::span_lint
;
6 use clippy_utils
::ty
::is_type_diagnostic_item
;
8 use rustc_lint
::{LateContext, LateLintPass}
;
9 use rustc_middle
::ty
::{self, Ty}
;
10 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
13 declare_clippy_lint
! {
15 /// Checks for usages of `Mutex<X>` where an atomic will do.
17 /// ### Why is this bad?
18 /// Using a mutex just to make access to a plain bool or
19 /// reference sequential is shooting flies with cannons.
20 /// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
23 /// ### Known problems
24 /// This lint cannot detect if the mutex is actually used
25 /// for waiting before a critical section.
30 /// # use std::sync::Mutex;
31 /// let x = Mutex::new(&y);
37 /// # use std::sync::atomic::AtomicBool;
38 /// let x = AtomicBool::new(y);
40 #[clippy::version = "pre 1.29.0"]
43 "using a mutex where an atomic value could be used instead"
46 declare_clippy_lint
! {
48 /// Checks for usages of `Mutex<X>` where `X` is an integral
51 /// ### Why is this bad?
52 /// Using a mutex just to make access to a plain integer
54 /// shooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster.
56 /// ### Known problems
57 /// This lint cannot detect if the mutex is actually used
58 /// for waiting before a critical section.
62 /// # use std::sync::Mutex;
63 /// let x = Mutex::new(0usize);
68 /// # use std::sync::atomic::AtomicUsize;
69 /// let x = AtomicUsize::new(0usize);
71 #[clippy::version = "pre 1.29.0"]
74 "using a mutex for an integer type"
77 declare_lint_pass
!(Mutex
=> [MUTEX_ATOMIC
, MUTEX_INTEGER
]);
79 impl<'tcx
> LateLintPass
<'tcx
> for Mutex
{
80 fn check_expr(&mut self, cx
: &LateContext
<'tcx
>, expr
: &'tcx Expr
<'_
>) {
81 let ty
= cx
.typeck_results().expr_ty(expr
);
82 if let ty
::Adt(_
, subst
) = ty
.kind() {
83 if is_type_diagnostic_item(cx
, ty
, sym
::Mutex
) {
84 let mutex_param
= subst
.type_at(0);
85 if let Some(atomic_name
) = get_atomic_name(mutex_param
) {
87 "consider using an `{}` instead of a `Mutex` here; if you just want the locking \
88 behavior and not the internal type, consider using `Mutex<()>`",
91 match *mutex_param
.kind() {
92 ty
::Uint(t
) if t
!= ty
::UintTy
::Usize
=> span_lint(cx
, MUTEX_INTEGER
, expr
.span
, &msg
),
93 ty
::Int(t
) if t
!= ty
::IntTy
::Isize
=> span_lint(cx
, MUTEX_INTEGER
, expr
.span
, &msg
),
94 _
=> span_lint(cx
, MUTEX_ATOMIC
, expr
.span
, &msg
),
102 fn get_atomic_name(ty
: Ty
<'_
>) -> Option
<&'
static str> {
104 ty
::Bool
=> Some("AtomicBool"),
105 ty
::Uint(_
) => Some("AtomicUsize"),
106 ty
::Int(_
) => Some("AtomicIsize"),
107 ty
::RawPtr(_
) => Some("AtomicPtr"),