]> git.lizzy.rs Git - rust.git/blob - src/docs/await_holding_lock.txt
Rollup merge of #104595 - compiler-errors:poly-existential-predicate, r=lcnr
[rust.git] / src / docs / await_holding_lock.txt
1 ### What it does
2 Checks for calls to await while holding a non-async-aware MutexGuard.
3
4 ### Why is this bad?
5 The Mutex types found in std::sync and parking_lot
6 are not designed to operate in an async context across await points.
7
8 There are two potential solutions. One is to use an async-aware Mutex
9 type. Many asynchronous foundation crates provide such a Mutex type. The
10 other solution is to ensure the mutex is unlocked before calling await,
11 either by introducing a scope or an explicit call to Drop::drop.
12
13 ### Known problems
14 Will report false positive for explicitly dropped guards
15 ([#6446](https://github.com/rust-lang/rust-clippy/issues/6446)). A workaround for this is
16 to wrap the `.lock()` call in a block instead of explicitly dropping the guard.
17
18 ### Example
19 ```
20 async fn foo(x: &Mutex<u32>) {
21   let mut guard = x.lock().unwrap();
22   *guard += 1;
23   baz().await;
24 }
25
26 async fn bar(x: &Mutex<u32>) {
27   let mut guard = x.lock().unwrap();
28   *guard += 1;
29   drop(guard); // explicit drop
30   baz().await;
31 }
32 ```
33
34 Use instead:
35 ```
36 async fn foo(x: &Mutex<u32>) {
37   {
38     let mut guard = x.lock().unwrap();
39     *guard += 1;
40   }
41   baz().await;
42 }
43
44 async fn bar(x: &Mutex<u32>) {
45   {
46     let mut guard = x.lock().unwrap();
47     *guard += 1;
48   } // guard dropped here at end of scope
49   baz().await;
50 }
51 ```