@@ -9,8 +9,7 @@ use rustc_span::Span;
99
1010declare_clippy_lint ! {
1111 /// ### What it does
12- /// Checks for calls to await while holding a
13- /// non-async-aware MutexGuard.
12+ /// Checks for calls to await while holding a non-async-aware MutexGuard.
1413 ///
1514 /// ### Why is this bad?
1615 /// The Mutex types found in std::sync and parking_lot
@@ -22,77 +21,110 @@ declare_clippy_lint! {
2221 /// either by introducing a scope or an explicit call to Drop::drop.
2322 ///
2423 /// ### Known problems
25- /// Will report false positive for explicitly dropped guards ([#6446](https://github.com/rust-lang/rust-clippy/issues/6446)).
24+ /// Will report false positive for explicitly dropped guards
25+ /// ([#6446](https://github.com/rust-lang/rust-clippy/issues/6446)). A workaround for this is
26+ /// to wrap the `.lock()` call in a block instead of explicitly dropping the guard.
2627 ///
2728 /// ### Example
28- /// ```rust,ignore
29- /// use std::sync::Mutex;
30- ///
29+ /// ```rust
30+ /// # use std::sync::Mutex;
31+ /// # async fn baz() {}
3132 /// async fn foo(x: &Mutex<u32>) {
32- /// let guard = x.lock().unwrap();
33+ /// let mut guard = x.lock().unwrap();
3334 /// *guard += 1;
34- /// bar.await;
35+ /// baz().await;
36+ /// }
37+ ///
38+ /// async fn bar(x: &Mutex<u32>) {
39+ /// let mut guard = x.lock().unwrap();
40+ /// *guard += 1;
41+ /// drop(guard); // explicit drop
42+ /// baz().await;
3543 /// }
3644 /// ```
3745 ///
3846 /// Use instead:
39- /// ```rust,ignore
40- /// use std::sync::Mutex;
41- ///
47+ /// ```rust
48+ /// # use std::sync::Mutex;
49+ /// # async fn baz() {}
4250 /// async fn foo(x: &Mutex<u32>) {
4351 /// {
44- /// let guard = x.lock().unwrap();
52+ /// let mut guard = x.lock().unwrap();
4553 /// *guard += 1;
4654 /// }
47- /// bar.await;
55+ /// baz().await;
56+ /// }
57+ ///
58+ /// async fn bar(x: &Mutex<u32>) {
59+ /// {
60+ /// let mut guard = x.lock().unwrap();
61+ /// *guard += 1;
62+ /// } // guard dropped here at end of scope
63+ /// baz().await;
4864 /// }
4965 /// ```
5066 #[ clippy:: version = "1.45.0" ]
5167 pub AWAIT_HOLDING_LOCK ,
52- pedantic ,
53- "Inside an async function, holding a MutexGuard while calling await"
68+ suspicious ,
69+ "inside an async function, holding a ` MutexGuard` while calling ` await` "
5470}
5571
5672declare_clippy_lint ! {
5773 /// ### What it does
58- /// Checks for calls to await while holding a
59- /// `RefCell` `Ref` or `RefMut`.
74+ /// Checks for calls to await while holding a `RefCell` `Ref` or `RefMut`.
6075 ///
6176 /// ### Why is this bad?
6277 /// `RefCell` refs only check for exclusive mutable access
6378 /// at runtime. Holding onto a `RefCell` ref across an `await` suspension point
6479 /// risks panics from a mutable ref shared while other refs are outstanding.
6580 ///
6681 /// ### Known problems
67- /// Will report false positive for explicitly dropped refs ([#6353](https://github.com/rust-lang/rust-clippy/issues/6353)).
82+ /// Will report false positive for explicitly dropped refs
83+ /// ([#6353](https://github.com/rust-lang/rust-clippy/issues/6353)). A workaround for this is
84+ /// to wrap the `.borrow[_mut]()` call in a block instead of explicitly dropping the ref.
6885 ///
6986 /// ### Example
70- /// ```rust,ignore
71- /// use std::cell::RefCell;
72- ///
87+ /// ```rust
88+ /// # use std::cell::RefCell;
89+ /// # async fn baz() {}
7390 /// async fn foo(x: &RefCell<u32>) {
7491 /// let mut y = x.borrow_mut();
7592 /// *y += 1;
76- /// bar.await;
93+ /// baz().await;
94+ /// }
95+ ///
96+ /// async fn bar(x: &RefCell<u32>) {
97+ /// let mut y = x.borrow_mut();
98+ /// *y += 1;
99+ /// drop(y); // explicit drop
100+ /// baz().await;
77101 /// }
78102 /// ```
79103 ///
80104 /// Use instead:
81- /// ```rust,ignore
82- /// use std::cell::RefCell;
83- ///
105+ /// ```rust
106+ /// # use std::cell::RefCell;
107+ /// # async fn baz() {}
84108 /// async fn foo(x: &RefCell<u32>) {
85109 /// {
86110 /// let mut y = x.borrow_mut();
87111 /// *y += 1;
88112 /// }
89- /// bar.await;
113+ /// baz().await;
114+ /// }
115+ ///
116+ /// async fn bar(x: &RefCell<u32>) {
117+ /// {
118+ /// let mut y = x.borrow_mut();
119+ /// *y += 1;
120+ /// } // y dropped here at end of scope
121+ /// baz().await;
90122 /// }
91123 /// ```
92124 #[ clippy:: version = "1.49.0" ]
93125 pub AWAIT_HOLDING_REFCELL_REF ,
94- pedantic ,
95- "Inside an async function, holding a RefCell ref while calling await"
126+ suspicious ,
127+ "inside an async function, holding a ` RefCell` ref while calling ` await` "
96128}
97129
98130declare_lint_pass ! ( AwaitHolding => [ AWAIT_HOLDING_LOCK , AWAIT_HOLDING_REFCELL_REF ] ) ;
0 commit comments