]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/mutex_atomic.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / mutex_atomic.rs
CommitLineData
49aad941 1//! Checks for usage of mutex where an atomic value could be used
f20569fa 2//!
9c376795 3//! This lint is **allow** by default
f20569fa 4
cdc7bbd5
XL
5use clippy_utils::diagnostics::span_lint;
6use clippy_utils::ty::is_type_diagnostic_item;
f20569fa
XL
7use rustc_hir::Expr;
8use rustc_lint::{LateContext, LateLintPass};
9use rustc_middle::ty::{self, Ty};
10use rustc_session::{declare_lint_pass, declare_tool_lint};
c295e0f8 11use rustc_span::sym;
f20569fa
XL
12
13declare_clippy_lint! {
94222f64 14 /// ### What it does
49aad941 15 /// Checks for usage of `Mutex<X>` where an atomic will do.
f20569fa 16 ///
94222f64
XL
17 /// ### Why is this bad?
18 /// Using a mutex just to make access to a plain bool or
f20569fa
XL
19 /// reference sequential is shooting flies with cannons.
20 /// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
21 /// faster.
22 ///
9c376795
FG
23 /// On the other hand, `Mutex`es are, in general, easier to
24 /// verify correctness. An atomic does not behave the same as
25 /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s commentary for more details.
26 ///
94222f64
XL
27 /// ### Known problems
28 /// This lint cannot detect if the mutex is actually used
f20569fa
XL
29 /// for waiting before a critical section.
30 ///
94222f64 31 /// ### Example
f20569fa
XL
32 /// ```rust
33 /// # let y = true;
f20569fa
XL
34 /// # use std::sync::Mutex;
35 /// let x = Mutex::new(&y);
923072b8 36 /// ```
f20569fa 37 ///
923072b8
FG
38 /// Use instead:
39 /// ```rust
40 /// # let y = true;
f20569fa
XL
41 /// # use std::sync::atomic::AtomicBool;
42 /// let x = AtomicBool::new(y);
43 /// ```
a2a8927a 44 #[clippy::version = "pre 1.29.0"]
f20569fa 45 pub MUTEX_ATOMIC,
9c376795
FG
46 restriction,
47 "using a mutex where an atomic value could be used instead."
f20569fa
XL
48}
49
50declare_clippy_lint! {
94222f64 51 /// ### What it does
49aad941 52 /// Checks for usage of `Mutex<X>` where `X` is an integral
f20569fa
XL
53 /// type.
54 ///
94222f64
XL
55 /// ### Why is this bad?
56 /// Using a mutex just to make access to a plain integer
f20569fa
XL
57 /// sequential is
58 /// shooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster.
59 ///
94222f64
XL
60 /// ### Known problems
61 /// This lint cannot detect if the mutex is actually used
f20569fa
XL
62 /// for waiting before a critical section.
63 ///
94222f64 64 /// ### Example
f20569fa
XL
65 /// ```rust
66 /// # use std::sync::Mutex;
67 /// let x = Mutex::new(0usize);
923072b8 68 /// ```
f20569fa 69 ///
923072b8
FG
70 /// Use instead:
71 /// ```rust
f20569fa
XL
72 /// # use std::sync::atomic::AtomicUsize;
73 /// let x = AtomicUsize::new(0usize);
74 /// ```
a2a8927a 75 #[clippy::version = "pre 1.29.0"]
f20569fa
XL
76 pub MUTEX_INTEGER,
77 nursery,
78 "using a mutex for an integer type"
79}
80
81declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]);
82
83impl<'tcx> LateLintPass<'tcx> for Mutex {
84 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
85 let ty = cx.typeck_results().expr_ty(expr);
86 if let ty::Adt(_, subst) = ty.kind() {
c295e0f8 87 if is_type_diagnostic_item(cx, ty, sym::Mutex) {
f20569fa
XL
88 let mutex_param = subst.type_at(0);
89 if let Some(atomic_name) = get_atomic_name(mutex_param) {
90 let msg = format!(
2b03887a
FG
91 "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \
92 behavior and not the internal type, consider using `Mutex<()>`"
f20569fa
XL
93 );
94 match *mutex_param.kind() {
95 ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
96 ty::Int(t) if t != ty::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
97 _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg),
98 };
99 }
100 }
101 }
102 }
103}
104
105fn get_atomic_name(ty: Ty<'_>) -> Option<&'static str> {
106 match ty.kind() {
107 ty::Bool => Some("AtomicBool"),
108 ty::Uint(_) => Some("AtomicUsize"),
109 ty::Int(_) => Some("AtomicIsize"),
110 ty::RawPtr(_) => Some("AtomicPtr"),
111 _ => None,
112 }
113}