Skip to content

Commit c4944fb

Browse files
committed
Actually lint parking_lot in await_holding_lock
This adapts the paths for the parking_lot mutex guards, so that parking_lot mutexes and RwLocks actually get linted. This is now also tested.
1 parent cdf9a28 commit c4944fb

File tree

3 files changed

+287
-103
lines changed

3 files changed

+287
-103
lines changed

clippy_utils/src/paths.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString",
105105
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
106106
pub const PARKING_LOT_RAWMUTEX: [&str; 3] = ["parking_lot", "raw_mutex", "RawMutex"];
107107
pub const PARKING_LOT_RAWRWLOCK: [&str; 3] = ["parking_lot", "raw_rwlock", "RawRwLock"];
108-
pub const PARKING_LOT_MUTEX_GUARD: [&str; 2] = ["parking_lot", "MutexGuard"];
109-
pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 2] = ["parking_lot", "RwLockReadGuard"];
110-
pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 2] = ["parking_lot", "RwLockWriteGuard"];
108+
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
109+
pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
110+
pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
111111
pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
112112
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
113113
pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];

tests/ui/await_holding_lock.rs

Lines changed: 147 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,178 @@
11
#![warn(clippy::await_holding_lock)]
22

3-
use std::sync::{Mutex, RwLock};
3+
// When adding or modifying a test, please do the same for parking_lot::Mutex.
4+
mod std_mutex {
5+
use std::sync::{Mutex, RwLock};
46

5-
async fn bad(x: &Mutex<u32>) -> u32 {
6-
let guard = x.lock().unwrap();
7-
baz().await
8-
}
7+
pub async fn bad(x: &Mutex<u32>) -> u32 {
8+
let guard = x.lock().unwrap();
9+
baz().await
10+
}
911

10-
async fn good(x: &Mutex<u32>) -> u32 {
11-
{
12+
pub async fn good(x: &Mutex<u32>) -> u32 {
13+
{
14+
let guard = x.lock().unwrap();
15+
let y = *guard + 1;
16+
}
17+
baz().await;
1218
let guard = x.lock().unwrap();
13-
let y = *guard + 1;
19+
47
1420
}
15-
baz().await;
16-
let guard = x.lock().unwrap();
17-
47
18-
}
1921

20-
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
21-
let guard = x.read().unwrap();
22-
baz().await
23-
}
22+
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
23+
let guard = x.read().unwrap();
24+
baz().await
25+
}
2426

25-
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
26-
let mut guard = x.write().unwrap();
27-
baz().await
28-
}
27+
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
28+
let mut guard = x.write().unwrap();
29+
baz().await
30+
}
2931

30-
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
31-
{
32+
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
33+
{
34+
let guard = x.read().unwrap();
35+
let y = *guard + 1;
36+
}
37+
{
38+
let mut guard = x.write().unwrap();
39+
*guard += 1;
40+
}
41+
baz().await;
3242
let guard = x.read().unwrap();
33-
let y = *guard + 1;
43+
47
3444
}
35-
{
36-
let mut guard = x.write().unwrap();
37-
*guard += 1;
45+
46+
pub async fn baz() -> u32 {
47+
42
3848
}
39-
baz().await;
40-
let guard = x.read().unwrap();
41-
47
42-
}
4349

44-
async fn baz() -> u32 {
45-
42
46-
}
50+
pub async fn also_bad(x: &Mutex<u32>) -> u32 {
51+
let first = baz().await;
52+
53+
let guard = x.lock().unwrap();
4754

48-
async fn also_bad(x: &Mutex<u32>) -> u32 {
49-
let first = baz().await;
55+
let second = baz().await;
5056

51-
let guard = x.lock().unwrap();
57+
let third = baz().await;
5258

53-
let second = baz().await;
59+
first + second + third
60+
}
61+
62+
pub async fn not_good(x: &Mutex<u32>) -> u32 {
63+
let first = baz().await;
64+
65+
let second = {
66+
let guard = x.lock().unwrap();
67+
baz().await
68+
};
5469

55-
let third = baz().await;
70+
let third = baz().await;
5671

57-
first + second + third
72+
first + second + third
73+
}
74+
75+
#[allow(clippy::manual_async_fn)]
76+
pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
77+
async move {
78+
let guard = x.lock().unwrap();
79+
baz().await
80+
}
81+
}
5882
}
5983

60-
async fn not_good(x: &Mutex<u32>) -> u32 {
61-
let first = baz().await;
84+
// When adding or modifying a test, please do the same for std::Mutex.
85+
mod parking_lot_mutex {
86+
use parking_lot::{Mutex, RwLock};
6287

63-
let second = {
64-
let guard = x.lock().unwrap();
88+
pub async fn bad(x: &Mutex<u32>) -> u32 {
89+
let guard = x.lock();
6590
baz().await
66-
};
91+
}
6792

68-
let third = baz().await;
93+
pub async fn good(x: &Mutex<u32>) -> u32 {
94+
{
95+
let guard = x.lock();
96+
let y = *guard + 1;
97+
}
98+
baz().await;
99+
let guard = x.lock();
100+
47
101+
}
69102

70-
first + second + third
71-
}
103+
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
104+
let guard = x.read();
105+
baz().await
106+
}
72107

73-
#[allow(clippy::manual_async_fn)]
74-
fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
75-
async move {
76-
let guard = x.lock().unwrap();
108+
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
109+
let mut guard = x.write();
77110
baz().await
78111
}
112+
113+
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
114+
{
115+
let guard = x.read();
116+
let y = *guard + 1;
117+
}
118+
{
119+
let mut guard = x.write();
120+
*guard += 1;
121+
}
122+
baz().await;
123+
let guard = x.read();
124+
47
125+
}
126+
127+
pub async fn baz() -> u32 {
128+
42
129+
}
130+
131+
pub async fn also_bad(x: &Mutex<u32>) -> u32 {
132+
let first = baz().await;
133+
134+
let guard = x.lock();
135+
136+
let second = baz().await;
137+
138+
let third = baz().await;
139+
140+
first + second + third
141+
}
142+
143+
pub async fn not_good(x: &Mutex<u32>) -> u32 {
144+
let first = baz().await;
145+
146+
let second = {
147+
let guard = x.lock();
148+
baz().await
149+
};
150+
151+
let third = baz().await;
152+
153+
first + second + third
154+
}
155+
156+
#[allow(clippy::manual_async_fn)]
157+
pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
158+
async move {
159+
let guard = x.lock();
160+
baz().await
161+
}
162+
}
79163
}
80164

81165
fn main() {
82-
let m = Mutex::new(100);
83-
good(&m);
84-
bad(&m);
85-
also_bad(&m);
86-
not_good(&m);
87-
block_bad(&m);
166+
let m = std::sync::Mutex::new(100);
167+
std_mutex::good(&m);
168+
std_mutex::bad(&m);
169+
std_mutex::also_bad(&m);
170+
std_mutex::not_good(&m);
171+
std_mutex::block_bad(&m);
172+
173+
let m = parking_lot::Mutex::new(100);
174+
parking_lot_mutex::good(&m);
175+
parking_lot_mutex::bad(&m);
176+
parking_lot_mutex::also_bad(&m);
177+
parking_lot_mutex::not_good(&m);
88178
}

0 commit comments

Comments
 (0)