Skip to content

Commit b63dddb

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 9fa6ffb commit b63dddb

File tree

3 files changed

+289
-103
lines changed

3 files changed

+289
-103
lines changed

clippy_utils/src/paths.rs

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

tests/ui/await_holding_lock.rs

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

3-
use std::sync::{Mutex, RwLock};
3+
extern crate parking_lot;
44

5-
async fn bad(x: &Mutex<u32>) -> u32 {
6-
let guard = x.lock().unwrap();
7-
baz().await
8-
}
5+
// When adding or modifying a test, please do the same for parking_lot::Mutex.
6+
mod std_mutex {
7+
use std::sync::{Mutex, RwLock};
98

10-
async fn good(x: &Mutex<u32>) -> u32 {
11-
{
9+
pub async fn bad(x: &Mutex<u32>) -> u32 {
1210
let guard = x.lock().unwrap();
13-
let y = *guard + 1;
11+
baz().await
1412
}
15-
baz().await;
16-
let guard = x.lock().unwrap();
17-
47
18-
}
1913

20-
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
21-
let guard = x.read().unwrap();
22-
baz().await
23-
}
24-
25-
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
26-
let mut guard = x.write().unwrap();
27-
baz().await
28-
}
14+
pub async fn good(x: &Mutex<u32>) -> u32 {
15+
{
16+
let guard = x.lock().unwrap();
17+
let y = *guard + 1;
18+
}
19+
baz().await;
20+
let guard = x.lock().unwrap();
21+
47
22+
}
2923

30-
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
31-
{
24+
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
3225
let guard = x.read().unwrap();
33-
let y = *guard + 1;
26+
baz().await
3427
}
35-
{
28+
29+
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
3630
let mut guard = x.write().unwrap();
37-
*guard += 1;
31+
baz().await
3832
}
39-
baz().await;
40-
let guard = x.read().unwrap();
41-
47
42-
}
4333

44-
async fn baz() -> u32 {
45-
42
46-
}
34+
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
35+
{
36+
let guard = x.read().unwrap();
37+
let y = *guard + 1;
38+
}
39+
{
40+
let mut guard = x.write().unwrap();
41+
*guard += 1;
42+
}
43+
baz().await;
44+
let guard = x.read().unwrap();
45+
47
46+
}
47+
48+
pub async fn baz() -> u32 {
49+
42
50+
}
51+
52+
pub async fn also_bad(x: &Mutex<u32>) -> u32 {
53+
let first = baz().await;
54+
55+
let guard = x.lock().unwrap();
56+
57+
let second = baz().await;
58+
59+
let third = baz().await;
4760

48-
async fn also_bad(x: &Mutex<u32>) -> u32 {
49-
let first = baz().await;
61+
first + second + third
62+
}
63+
64+
pub async fn not_good(x: &Mutex<u32>) -> u32 {
65+
let first = baz().await;
5066

51-
let guard = x.lock().unwrap();
67+
let second = {
68+
let guard = x.lock().unwrap();
69+
baz().await
70+
};
5271

53-
let second = baz().await;
72+
let third = baz().await;
5473

55-
let third = baz().await;
74+
first + second + third
75+
}
5676

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

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

63-
let second = {
64-
let guard = x.lock().unwrap();
90+
pub async fn bad(x: &Mutex<u32>) -> u32 {
91+
let guard = x.lock();
6592
baz().await
66-
};
93+
}
6794

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

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

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

81167
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);
168+
let m = std::sync::Mutex::new(100);
169+
std_mutex::good(&m);
170+
std_mutex::bad(&m);
171+
std_mutex::also_bad(&m);
172+
std_mutex::not_good(&m);
173+
std_mutex::block_bad(&m);
174+
175+
let m = parking_lot::Mutex::new(100);
176+
parking_lot_mutex::good(&m);
177+
parking_lot_mutex::bad(&m);
178+
parking_lot_mutex::also_bad(&m);
179+
parking_lot_mutex::not_good(&m);
88180
}

0 commit comments

Comments
 (0)