]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/tests/ui/await_holding_lock.rs
New upstream version 1.61.0+dfsg1
[rustc.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 }