Skip to content

Commit 38ac3d0

Browse files
committed
only lint on definitions, not use
1 parent 3ae047e commit 38ac3d0

File tree

3 files changed

+126
-64
lines changed

3 files changed

+126
-64
lines changed

clippy_lints/src/mutex_atomic.rs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::res::MaybeDef;
3+
use clippy_utils::ty::ty_from_hir_ty;
34
use rustc_errors::Diag;
4-
use rustc_hir::Expr;
5+
use rustc_hir::{Expr, Item, ItemKind, LetStmt};
56
use rustc_lint::{LateContext, LateLintPass};
67
use rustc_middle::ty::{self, IntTy, Ty, UintTy};
78
use rustc_session::declare_lint_pass;
@@ -89,26 +90,43 @@ declare_clippy_lint! {
8990

9091
declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]);
9192

93+
// NOTE: we don't use `check_expr` because that would make us lint every _use_ of such mutexes, not
94+
// just their definitions
9295
impl<'tcx> LateLintPass<'tcx> for Mutex {
93-
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
94-
let ty = cx.typeck_results().expr_ty(expr);
95-
if let ty::Adt(_, subst) = ty.kind()
96-
&& ty.is_diag_item(cx, sym::Mutex)
97-
&& let mutex_param = subst.type_at(0)
98-
&& let Some(atomic_name) = get_atomic_name(mutex_param)
96+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
97+
if !item.span.from_expansion()
98+
&& let ItemKind::Static(_, _, ty, body_id) = item.kind
9999
{
100-
let msg = "using a `Mutex` where an atomic would do";
101-
let diag = |diag: &mut Diag<'_, _>| {
102-
diag.help(format!("consider using an `{atomic_name}` instead"));
103-
diag.help(
104-
"if you just want the locking behavior and not the internal type, consider using `Mutex<()>`",
105-
);
106-
};
107-
match *mutex_param.kind() {
108-
ty::Uint(t) if t != UintTy::Usize => span_lint_and_then(cx, MUTEX_INTEGER, expr.span, msg, diag),
109-
ty::Int(t) if t != IntTy::Isize => span_lint_and_then(cx, MUTEX_INTEGER, expr.span, msg, diag),
110-
_ => span_lint_and_then(cx, MUTEX_ATOMIC, expr.span, msg, diag),
111-
}
100+
let body = cx.tcx.hir_body(body_id);
101+
let mid_ty = ty_from_hir_ty(cx, ty);
102+
check_expr(cx, body.value.peel_blocks(), mid_ty);
103+
}
104+
}
105+
fn check_local(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx LetStmt<'_>) {
106+
if !stmt.span.from_expansion()
107+
&& let Some(init) = stmt.init
108+
{
109+
let mid_ty = cx.typeck_results().expr_ty(init);
110+
check_expr(cx, init.peel_blocks(), mid_ty);
111+
}
112+
}
113+
}
114+
115+
fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, ty: Ty<'tcx>) {
116+
if let ty::Adt(_, subst) = ty.kind()
117+
&& ty.is_diag_item(cx, sym::Mutex)
118+
&& let mutex_param = subst.type_at(0)
119+
&& let Some(atomic_name) = get_atomic_name(mutex_param)
120+
{
121+
let msg = "using a `Mutex` where an atomic would do";
122+
let diag = |diag: &mut Diag<'_, _>| {
123+
diag.help(format!("consider using an `{atomic_name}` instead"));
124+
diag.help("if you just want the locking behavior and not the internal type, consider using `Mutex<()>`");
125+
};
126+
match *mutex_param.kind() {
127+
ty::Uint(t) if t != UintTy::Usize => span_lint_and_then(cx, MUTEX_INTEGER, expr.span, msg, diag),
128+
ty::Int(t) if t != IntTy::Isize => span_lint_and_then(cx, MUTEX_INTEGER, expr.span, msg, diag),
129+
_ => span_lint_and_then(cx, MUTEX_ATOMIC, expr.span, msg, diag),
112130
}
113131
}
114132
}

tests/ui/mutex_atomic.rs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,64 @@
22
#![warn(clippy::mutex_atomic)]
33
#![allow(clippy::borrow_as_ptr)]
44

5+
use std::sync::Mutex;
6+
57
fn main() {
6-
use std::sync::Mutex;
7-
Mutex::new(true);
8+
let _ = Mutex::new(true);
89
//~^ mutex_atomic
910

10-
Mutex::new(5usize);
11+
let _ = Mutex::new(5usize);
1112
//~^ mutex_atomic
1213

13-
Mutex::new(9isize);
14+
let _ = Mutex::new(9isize);
1415
//~^ mutex_atomic
1516

1617
let mut x = 4u32;
17-
Mutex::new(&x as *const u32);
18+
let _ = Mutex::new(&x as *const u32);
1819
//~^ mutex_atomic
1920

20-
Mutex::new(&mut x as *mut u32);
21+
let _ = Mutex::new(&mut x as *mut u32);
2122
//~^ mutex_atomic
2223

23-
Mutex::new(0u32);
24+
let _ = Mutex::new(0u32);
2425
//~^ mutex_integer
2526

26-
Mutex::new(0i32);
27+
let _ = Mutex::new(0i32);
2728
//~^ mutex_integer
2829

29-
Mutex::new(0f32); // there are no float atomics, so this should not lint
30-
Mutex::new(0u8);
30+
let _ = Mutex::new(0f32); // there are no float atomics, so this should not lint
31+
let _ = Mutex::new(0u8);
3132
//~^ mutex_integer
3233

33-
Mutex::new(0i16);
34+
let _ = Mutex::new(0i16);
3435
//~^ mutex_integer
3536

3637
let _x: Mutex<i8> = Mutex::new(0);
3738
//~^ mutex_integer
3839

3940
const X: i64 = 0;
40-
Mutex::new(X);
41+
let _ = Mutex::new(X);
4142
//~^ mutex_integer
4243

4344
// there are no 128 atomics, so these two should not lint
4445
{
45-
Mutex::new(0u128);
46+
let _ = Mutex::new(0u128);
4647
let _x: Mutex<i128> = Mutex::new(0);
4748
}
4849
}
50+
51+
static MTX: Mutex<u32> = Mutex::new(0);
52+
//~^ mutex_integer
53+
54+
// don't lint on _use_, only declaration
55+
fn issue13378() {
56+
let mut guard = MTX.lock().unwrap();
57+
*guard += 1;
58+
59+
let mtx = Mutex::new(0);
60+
//~^ mutex_integer
61+
// This will still lint, since we're reassigning the mutex to a variable -- oh well.
62+
// But realistically something like this won't really come up.
63+
let reassigned = mtx;
64+
//~^ mutex_integer
65+
}

tests/ui/mutex_atomic.stderr

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,90 @@
11
error: using a `Mutex` where an atomic would do
2-
--> tests/ui/mutex_atomic.rs:7:5
2+
--> tests/ui/mutex_atomic.rs:8:13
33
|
4-
LL | Mutex::new(true);
5-
| ^^^^^^^^^^^^^^^^
4+
LL | let _ = Mutex::new(true);
5+
| ^^^^^^^^^^^^^^^^
66
|
77
= help: consider using an `AtomicBool` instead
88
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
99
= note: `-D clippy::mutex-atomic` implied by `-D warnings`
1010
= help: to override `-D warnings` add `#[allow(clippy::mutex_atomic)]`
1111

1212
error: using a `Mutex` where an atomic would do
13-
--> tests/ui/mutex_atomic.rs:10:5
13+
--> tests/ui/mutex_atomic.rs:11:13
1414
|
15-
LL | Mutex::new(5usize);
16-
| ^^^^^^^^^^^^^^^^^^
15+
LL | let _ = Mutex::new(5usize);
16+
| ^^^^^^^^^^^^^^^^^^
1717
|
1818
= help: consider using an `AtomicUsize` instead
1919
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
2020

2121
error: using a `Mutex` where an atomic would do
22-
--> tests/ui/mutex_atomic.rs:13:5
22+
--> tests/ui/mutex_atomic.rs:14:13
2323
|
24-
LL | Mutex::new(9isize);
25-
| ^^^^^^^^^^^^^^^^^^
24+
LL | let _ = Mutex::new(9isize);
25+
| ^^^^^^^^^^^^^^^^^^
2626
|
2727
= help: consider using an `AtomicIsize` instead
2828
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
2929

3030
error: using a `Mutex` where an atomic would do
31-
--> tests/ui/mutex_atomic.rs:17:5
31+
--> tests/ui/mutex_atomic.rs:18:13
3232
|
33-
LL | Mutex::new(&x as *const u32);
34-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33+
LL | let _ = Mutex::new(&x as *const u32);
34+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3535
|
3636
= help: consider using an `AtomicPtr` instead
3737
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
3838

3939
error: using a `Mutex` where an atomic would do
40-
--> tests/ui/mutex_atomic.rs:20:5
40+
--> tests/ui/mutex_atomic.rs:21:13
4141
|
42-
LL | Mutex::new(&mut x as *mut u32);
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
LL | let _ = Mutex::new(&mut x as *mut u32);
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4444
|
4545
= help: consider using an `AtomicPtr` instead
4646
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
4747

4848
error: using a `Mutex` where an atomic would do
49-
--> tests/ui/mutex_atomic.rs:23:5
49+
--> tests/ui/mutex_atomic.rs:24:13
5050
|
51-
LL | Mutex::new(0u32);
52-
| ^^^^^^^^^^^^^^^^
51+
LL | let _ = Mutex::new(0u32);
52+
| ^^^^^^^^^^^^^^^^
5353
|
5454
= help: consider using an `AtomicU32` instead
5555
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
5656
= note: `-D clippy::mutex-integer` implied by `-D warnings`
5757
= help: to override `-D warnings` add `#[allow(clippy::mutex_integer)]`
5858

5959
error: using a `Mutex` where an atomic would do
60-
--> tests/ui/mutex_atomic.rs:26:5
60+
--> tests/ui/mutex_atomic.rs:27:13
6161
|
62-
LL | Mutex::new(0i32);
63-
| ^^^^^^^^^^^^^^^^
62+
LL | let _ = Mutex::new(0i32);
63+
| ^^^^^^^^^^^^^^^^
6464
|
6565
= help: consider using an `AtomicI32` instead
6666
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
6767

6868
error: using a `Mutex` where an atomic would do
69-
--> tests/ui/mutex_atomic.rs:30:5
69+
--> tests/ui/mutex_atomic.rs:31:13
7070
|
71-
LL | Mutex::new(0u8);
72-
| ^^^^^^^^^^^^^^^
71+
LL | let _ = Mutex::new(0u8);
72+
| ^^^^^^^^^^^^^^^
7373
|
7474
= help: consider using an `AtomicU8` instead
7575
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
7676

7777
error: using a `Mutex` where an atomic would do
78-
--> tests/ui/mutex_atomic.rs:33:5
78+
--> tests/ui/mutex_atomic.rs:34:13
7979
|
80-
LL | Mutex::new(0i16);
81-
| ^^^^^^^^^^^^^^^^
80+
LL | let _ = Mutex::new(0i16);
81+
| ^^^^^^^^^^^^^^^^
8282
|
8383
= help: consider using an `AtomicI16` instead
8484
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
8585

8686
error: using a `Mutex` where an atomic would do
87-
--> tests/ui/mutex_atomic.rs:36:25
87+
--> tests/ui/mutex_atomic.rs:37:25
8888
|
8989
LL | let _x: Mutex<i8> = Mutex::new(0);
9090
| ^^^^^^^^^^^^^
@@ -93,13 +93,40 @@ LL | let _x: Mutex<i8> = Mutex::new(0);
9393
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
9494

9595
error: using a `Mutex` where an atomic would do
96-
--> tests/ui/mutex_atomic.rs:40:5
96+
--> tests/ui/mutex_atomic.rs:41:13
9797
|
98-
LL | Mutex::new(X);
99-
| ^^^^^^^^^^^^^
98+
LL | let _ = Mutex::new(X);
99+
| ^^^^^^^^^^^^^
100100
|
101101
= help: consider using an `AtomicI64` instead
102102
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
103103

104-
error: aborting due to 11 previous errors
104+
error: using a `Mutex` where an atomic would do
105+
--> tests/ui/mutex_atomic.rs:51:26
106+
|
107+
LL | static MTX: Mutex<u32> = Mutex::new(0);
108+
| ^^^^^^^^^^^^^
109+
|
110+
= help: consider using an `AtomicU32` instead
111+
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
112+
113+
error: using a `Mutex` where an atomic would do
114+
--> tests/ui/mutex_atomic.rs:59:15
115+
|
116+
LL | let mtx = Mutex::new(0);
117+
| ^^^^^^^^^^^^^
118+
|
119+
= help: consider using an `AtomicI32` instead
120+
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
121+
122+
error: using a `Mutex` where an atomic would do
123+
--> tests/ui/mutex_atomic.rs:63:22
124+
|
125+
LL | let reassigned = mtx;
126+
| ^^^
127+
|
128+
= help: consider using an `AtomicI32` instead
129+
= help: if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
130+
131+
error: aborting due to 14 previous errors
105132

0 commit comments

Comments
 (0)