]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/await_holding_lock.rs
Rollup merge of #102412 - joboet:dont_panic, r=m-ou-se
[rust.git] / src / tools / clippy / tests / ui / await_holding_lock.rs
1 #![warn(clippy::await_holding_lock)]
2
3 // When adding or modifying a test, please do the same for parking_lot::Mutex.
4 mod std_mutex {
5     use super::baz;
6     use std::sync::{Mutex, RwLock};
7
8     pub async fn bad(x: &Mutex<u32>) -> u32 {
9         let guard = x.lock().unwrap();
10         baz().await
11     }
12
13     pub async fn good(x: &Mutex<u32>) -> u32 {
14         {
15             let guard = x.lock().unwrap();
16             let y = *guard + 1;
17         }
18         baz().await;
19         let guard = x.lock().unwrap();
20         47
21     }
22
23     pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
24         let guard = x.read().unwrap();
25         baz().await
26     }
27
28     pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
29         let mut guard = x.write().unwrap();
30         baz().await
31     }
32
33     pub async fn good_rw(x: &RwLock<u32>) -> u32 {
34         {
35             let guard = x.read().unwrap();
36             let y = *guard + 1;
37         }
38         {
39             let mut guard = x.write().unwrap();
40             *guard += 1;
41         }
42         baz().await;
43         let guard = x.read().unwrap();
44         47
45     }
46
47     pub async fn also_bad(x: &Mutex<u32>) -> u32 {
48         let first = baz().await;
49
50         let guard = x.lock().unwrap();
51
52         let second = baz().await;
53
54         let third = baz().await;
55
56         first + second + third
57     }
58
59     pub async fn not_good(x: &Mutex<u32>) -> u32 {
60         let first = baz().await;
61
62         let second = {
63             let guard = x.lock().unwrap();
64             baz().await
65         };
66
67         let third = baz().await;
68
69         first + second + third
70     }
71
72     #[allow(clippy::manual_async_fn)]
73     pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
74         async move {
75             let guard = x.lock().unwrap();
76             baz().await
77         }
78     }
79 }
80
81 // When adding or modifying a test, please do the same for std::Mutex.
82 mod parking_lot_mutex {
83     use super::baz;
84     use parking_lot::{Mutex, RwLock};
85
86     pub async fn bad(x: &Mutex<u32>) -> u32 {
87         let guard = x.lock();
88         baz().await
89     }
90
91     pub async fn good(x: &Mutex<u32>) -> u32 {
92         {
93             let guard = x.lock();
94             let y = *guard + 1;
95         }
96         baz().await;
97         let guard = x.lock();
98         47
99     }
100
101     pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
102         let guard = x.read();
103         baz().await
104     }
105
106     pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
107         let mut guard = x.write();
108         baz().await
109     }
110
111     pub async fn good_rw(x: &RwLock<u32>) -> u32 {
112         {
113             let guard = x.read();
114             let y = *guard + 1;
115         }
116         {
117             let mut guard = x.write();
118             *guard += 1;
119         }
120         baz().await;
121         let guard = x.read();
122         47
123     }
124
125     pub async fn also_bad(x: &Mutex<u32>) -> u32 {
126         let first = baz().await;
127
128         let guard = x.lock();
129
130         let second = baz().await;
131
132         let third = baz().await;
133
134         first + second + third
135     }
136
137     pub async fn not_good(x: &Mutex<u32>) -> u32 {
138         let first = baz().await;
139
140         let second = {
141             let guard = x.lock();
142             baz().await
143         };
144
145         let third = baz().await;
146
147         first + second + third
148     }
149
150     #[allow(clippy::manual_async_fn)]
151     pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
152         async move {
153             let guard = x.lock();
154             baz().await
155         }
156     }
157 }
158
159 async fn baz() -> u32 {
160     42
161 }
162
163 async fn no_await(x: std::sync::Mutex<u32>) {
164     let mut guard = x.lock().unwrap();
165     *guard += 1;
166 }
167
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();
174     *guard += 1;
175     drop(guard);
176     baz().await;
177 }
178
179 fn main() {
180     let m = std::sync::Mutex::new(100);
181     std_mutex::good(&m);
182     std_mutex::bad(&m);
183     std_mutex::also_bad(&m);
184     std_mutex::not_good(&m);
185     std_mutex::block_bad(&m);
186
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);
192 }