1 #![warn(clippy::await_holding_lock)]
3 // When adding or modifying a test, please do the same for parking_lot::Mutex.
6 use std::sync::{Mutex, RwLock};
8 pub async fn bad(x: &Mutex<u32>) -> u32 {
9 let guard = x.lock().unwrap();
13 pub async fn good(x: &Mutex<u32>) -> u32 {
15 let guard = x.lock().unwrap();
19 let guard = x.lock().unwrap();
23 pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
24 let guard = x.read().unwrap();
28 pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
29 let mut guard = x.write().unwrap();
33 pub async fn good_rw(x: &RwLock<u32>) -> u32 {
35 let guard = x.read().unwrap();
39 let mut guard = x.write().unwrap();
43 let guard = x.read().unwrap();
47 pub async fn also_bad(x: &Mutex<u32>) -> u32 {
48 let first = baz().await;
50 let guard = x.lock().unwrap();
52 let second = baz().await;
54 let third = baz().await;
56 first + second + third
59 pub async fn not_good(x: &Mutex<u32>) -> u32 {
60 let first = baz().await;
63 let guard = x.lock().unwrap();
67 let third = baz().await;
69 first + second + third
72 #[allow(clippy::manual_async_fn)]
73 pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
75 let guard = x.lock().unwrap();
81 // When adding or modifying a test, please do the same for std::Mutex.
82 mod parking_lot_mutex {
84 use parking_lot::{Mutex, RwLock};
86 pub async fn bad(x: &Mutex<u32>) -> u32 {
91 pub async fn good(x: &Mutex<u32>) -> u32 {
101 pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
102 let guard = x.read();
106 pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
107 let mut guard = x.write();
111 pub async fn good_rw(x: &RwLock<u32>) -> u32 {
113 let guard = x.read();
117 let mut guard = x.write();
121 let guard = x.read();
125 pub async fn also_bad(x: &Mutex<u32>) -> u32 {
126 let first = baz().await;
128 let guard = x.lock();
130 let second = baz().await;
132 let third = baz().await;
134 first + second + third
137 pub async fn not_good(x: &Mutex<u32>) -> u32 {
138 let first = baz().await;
141 let guard = x.lock();
145 let third = baz().await;
147 first + second + third
150 #[allow(clippy::manual_async_fn)]
151 pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
153 let guard = x.lock();
159 async fn baz() -> u32 {
163 async fn no_await(x: std::sync::Mutex<u32>) {
164 let mut guard = x.lock().unwrap();
168 // FIXME: FP, because the `MutexGuard` is dropped before crossing the await point. This is
169 // something the needs to be fixed in rustc. There's already drop-tracking, but this is currently
170 // disabled, see rust-lang/rust#93751. This case isn't picked up by drop-tracking though. If the
171 // `*guard += 1` is removed it is picked up.
172 async fn dropped_before_await(x: std::sync::Mutex<u32>) {
173 let mut guard = x.lock().unwrap();
180 let m = std::sync::Mutex::new(100);
183 std_mutex::also_bad(&m);
184 std_mutex::not_good(&m);
185 std_mutex::block_bad(&m);
187 let m = parking_lot::Mutex::new(100);
188 parking_lot_mutex::good(&m);
189 parking_lot_mutex::bad(&m);
190 parking_lot_mutex::also_bad(&m);
191 parking_lot_mutex::not_good(&m);