Auto merge of #8419 - flip1995:await_parking_alot, r=llogiq

Fix `await_holding_lock` not linting `parking_lot` Mutex/RwLock

This adds tests for `RwLock` and `parking_lot::{Mutex, RwLock}`, which were added before in 2dc8c083f5, but never tested in UI tests. I noticed this while reading [fasterthanli.me](https://fasterthanli.me/articles/a-rust-match-made-in-hell) latest blog post, complaining that Clippy doesn't catch this for `parking_lot`. (Too many people read his blog, he's too powerful)

Some more things:
- Adds a test for #6446
- Improves the lint message

changelog: [`await_holding_lock`]: Now also lints for `parking_lot::{Mutex, RwLock}`
This commit is contained in:
bors 2022-02-18 10:55:05 +00:00
commit 02f3c17593
8 changed files with 479 additions and 153 deletions

View File

@ -1,4 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths};
use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
@ -9,8 +9,7 @@ use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
/// Checks for calls to await while holding a
/// non-async-aware MutexGuard.
/// Checks for calls to await while holding a non-async-aware MutexGuard.
///
/// ### Why is this bad?
/// The Mutex types found in std::sync and parking_lot
@ -22,41 +21,57 @@ declare_clippy_lint! {
/// either by introducing a scope or an explicit call to Drop::drop.
///
/// ### Known problems
/// Will report false positive for explicitly dropped guards ([#6446](https://github.com/rust-lang/rust-clippy/issues/6446)).
/// Will report false positive for explicitly dropped guards
/// ([#6446](https://github.com/rust-lang/rust-clippy/issues/6446)). A workaround for this is
/// to wrap the `.lock()` call in a block instead of explicitly dropping the guard.
///
/// ### Example
/// ```rust,ignore
/// use std::sync::Mutex;
///
/// ```rust
/// # use std::sync::Mutex;
/// # async fn baz() {}
/// async fn foo(x: &Mutex<u32>) {
/// let guard = x.lock().unwrap();
/// let mut guard = x.lock().unwrap();
/// *guard += 1;
/// bar.await;
/// baz().await;
/// }
///
/// async fn bar(x: &Mutex<u32>) {
/// let mut guard = x.lock().unwrap();
/// *guard += 1;
/// drop(guard); // explicit drop
/// baz().await;
/// }
/// ```
///
/// Use instead:
/// ```rust,ignore
/// use std::sync::Mutex;
///
/// ```rust
/// # use std::sync::Mutex;
/// # async fn baz() {}
/// async fn foo(x: &Mutex<u32>) {
/// {
/// let guard = x.lock().unwrap();
/// let mut guard = x.lock().unwrap();
/// *guard += 1;
/// }
/// bar.await;
/// baz().await;
/// }
///
/// async fn bar(x: &Mutex<u32>) {
/// {
/// let mut guard = x.lock().unwrap();
/// *guard += 1;
/// } // guard dropped here at end of scope
/// baz().await;
/// }
/// ```
#[clippy::version = "1.45.0"]
pub AWAIT_HOLDING_LOCK,
pedantic,
"Inside an async function, holding a MutexGuard while calling await"
suspicious,
"inside an async function, holding a `MutexGuard` while calling `await`"
}
declare_clippy_lint! {
/// ### What it does
/// Checks for calls to await while holding a
/// `RefCell` `Ref` or `RefMut`.
/// Checks for calls to await while holding a `RefCell` `Ref` or `RefMut`.
///
/// ### Why is this bad?
/// `RefCell` refs only check for exclusive mutable access
@ -64,35 +79,52 @@ declare_clippy_lint! {
/// risks panics from a mutable ref shared while other refs are outstanding.
///
/// ### Known problems
/// Will report false positive for explicitly dropped refs ([#6353](https://github.com/rust-lang/rust-clippy/issues/6353)).
/// Will report false positive for explicitly dropped refs
/// ([#6353](https://github.com/rust-lang/rust-clippy/issues/6353)). A workaround for this is
/// to wrap the `.borrow[_mut]()` call in a block instead of explicitly dropping the ref.
///
/// ### Example
/// ```rust,ignore
/// use std::cell::RefCell;
///
/// ```rust
/// # use std::cell::RefCell;
/// # async fn baz() {}
/// async fn foo(x: &RefCell<u32>) {
/// let mut y = x.borrow_mut();
/// *y += 1;
/// bar.await;
/// baz().await;
/// }
///
/// async fn bar(x: &RefCell<u32>) {
/// let mut y = x.borrow_mut();
/// *y += 1;
/// drop(y); // explicit drop
/// baz().await;
/// }
/// ```
///
/// Use instead:
/// ```rust,ignore
/// use std::cell::RefCell;
///
/// ```rust
/// # use std::cell::RefCell;
/// # async fn baz() {}
/// async fn foo(x: &RefCell<u32>) {
/// {
/// let mut y = x.borrow_mut();
/// *y += 1;
/// }
/// bar.await;
/// baz().await;
/// }
///
/// async fn bar(x: &RefCell<u32>) {
/// {
/// let mut y = x.borrow_mut();
/// *y += 1;
/// } // y dropped here at end of scope
/// baz().await;
/// }
/// ```
#[clippy::version = "1.49.0"]
pub AWAIT_HOLDING_REFCELL_REF,
pedantic,
"Inside an async function, holding a RefCell ref while calling await"
suspicious,
"inside an async function, holding a `RefCell` ref while calling `await`"
}
declare_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF]);
@ -118,23 +150,36 @@ fn check_interior_types(cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorType
for ty_cause in ty_causes {
if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
if is_mutex_guard(cx, adt.did) {
span_lint_and_note(
span_lint_and_then(
cx,
AWAIT_HOLDING_LOCK,
ty_cause.span,
"this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await",
ty_cause.scope_span.or(Some(span)),
"these are all the await points this lock is held through",
"this `MutexGuard` is held across an `await` point",
|diag| {
diag.help(
"consider using an async-aware `Mutex` type or ensuring the \
`MutexGuard` is dropped before calling await",
);
diag.span_note(
ty_cause.scope_span.unwrap_or(span),
"these are all the `await` points this lock is held through",
);
},
);
}
if is_refcell_ref(cx, adt.did) {
span_lint_and_note(
span_lint_and_then(
cx,
AWAIT_HOLDING_REFCELL_REF,
ty_cause.span,
"this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await",
ty_cause.scope_span.or(Some(span)),
"these are all the await points this ref is held through",
"this `RefCell` reference is held across an `await` point",
|diag| {
diag.help("ensure the reference is dropped before calling `await`");
diag.span_note(
ty_cause.scope_span.unwrap_or(span),
"these are all the `await` points this reference is held through",
);
},
);
}
}

View File

@ -14,6 +14,8 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(attrs::DEPRECATED_SEMVER),
LintId::of(attrs::MISMATCHED_TARGET_OS),
LintId::of(attrs::USELESS_ATTRIBUTE),
LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
LintId::of(bit_mask::BAD_BIT_MASK),
LintId::of(bit_mask::INEFFECTIVE_BIT_MASK),
LintId::of(blacklisted_name::BLACKLISTED_NAME),

View File

@ -4,8 +4,6 @@
store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
LintId::of(attrs::INLINE_ALWAYS),
LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
LintId::of(bit_mask::VERBOSE_BIT_MASK),
LintId::of(borrow_as_ptr::BORROW_AS_PTR),
LintId::of(bytecount::NAIVE_BYTECOUNT),

View File

@ -5,6 +5,8 @@
store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec![
LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),

View File

@ -105,9 +105,9 @@ pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString",
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub const PARKING_LOT_RAWMUTEX: [&str; 3] = ["parking_lot", "raw_mutex", "RawMutex"];
pub const PARKING_LOT_RAWRWLOCK: [&str; 3] = ["parking_lot", "raw_rwlock", "RawRwLock"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 2] = ["parking_lot", "MutexGuard"];
pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 2] = ["parking_lot", "RwLockReadGuard"];
pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 2] = ["parking_lot", "RwLockWriteGuard"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];

View File

@ -1,64 +1,192 @@
#![warn(clippy::await_holding_lock)]
use std::sync::Mutex;
// When adding or modifying a test, please do the same for parking_lot::Mutex.
mod std_mutex {
use super::baz;
use std::sync::{Mutex, RwLock};
async fn bad(x: &Mutex<u32>) -> u32 {
let guard = x.lock().unwrap();
baz().await
pub async fn bad(x: &Mutex<u32>) -> u32 {
let guard = x.lock().unwrap();
baz().await
}
pub async fn good(x: &Mutex<u32>) -> u32 {
{
let guard = x.lock().unwrap();
let y = *guard + 1;
}
baz().await;
let guard = x.lock().unwrap();
47
}
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
let guard = x.read().unwrap();
baz().await
}
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
let mut guard = x.write().unwrap();
baz().await
}
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
{
let guard = x.read().unwrap();
let y = *guard + 1;
}
{
let mut guard = x.write().unwrap();
*guard += 1;
}
baz().await;
let guard = x.read().unwrap();
47
}
pub async fn also_bad(x: &Mutex<u32>) -> u32 {
let first = baz().await;
let guard = x.lock().unwrap();
let second = baz().await;
let third = baz().await;
first + second + third
}
pub async fn not_good(x: &Mutex<u32>) -> u32 {
let first = baz().await;
let second = {
let guard = x.lock().unwrap();
baz().await
};
let third = baz().await;
first + second + third
}
#[allow(clippy::manual_async_fn)]
pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
async move {
let guard = x.lock().unwrap();
baz().await
}
}
}
async fn good(x: &Mutex<u32>) -> u32 {
{
let guard = x.lock().unwrap();
let y = *guard + 1;
// When adding or modifying a test, please do the same for std::Mutex.
mod parking_lot_mutex {
use super::baz;
use parking_lot::{Mutex, RwLock};
pub async fn bad(x: &Mutex<u32>) -> u32 {
let guard = x.lock();
baz().await
}
pub async fn good(x: &Mutex<u32>) -> u32 {
{
let guard = x.lock();
let y = *guard + 1;
}
baz().await;
let guard = x.lock();
47
}
pub async fn bad_rw(x: &RwLock<u32>) -> u32 {
let guard = x.read();
baz().await
}
pub async fn bad_rw_write(x: &RwLock<u32>) -> u32 {
let mut guard = x.write();
baz().await
}
pub async fn good_rw(x: &RwLock<u32>) -> u32 {
{
let guard = x.read();
let y = *guard + 1;
}
{
let mut guard = x.write();
*guard += 1;
}
baz().await;
let guard = x.read();
47
}
pub async fn also_bad(x: &Mutex<u32>) -> u32 {
let first = baz().await;
let guard = x.lock();
let second = baz().await;
let third = baz().await;
first + second + third
}
pub async fn not_good(x: &Mutex<u32>) -> u32 {
let first = baz().await;
let second = {
let guard = x.lock();
baz().await
};
let third = baz().await;
first + second + third
}
#[allow(clippy::manual_async_fn)]
pub fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
async move {
let guard = x.lock();
baz().await
}
}
baz().await;
let guard = x.lock().unwrap();
47
}
async fn baz() -> u32 {
42
}
async fn also_bad(x: &Mutex<u32>) -> u32 {
let first = baz().await;
let guard = x.lock().unwrap();
let second = baz().await;
let third = baz().await;
first + second + third
async fn no_await(x: std::sync::Mutex<u32>) {
let mut guard = x.lock().unwrap();
*guard += 1;
}
async fn not_good(x: &Mutex<u32>) -> u32 {
let first = baz().await;
let second = {
let guard = x.lock().unwrap();
baz().await
};
let third = baz().await;
first + second + third
}
#[allow(clippy::manual_async_fn)]
fn block_bad(x: &Mutex<u32>) -> impl std::future::Future<Output = u32> + '_ {
async move {
let guard = x.lock().unwrap();
baz().await
}
// FIXME: FP, because the `MutexGuard` is dropped before crossing the await point. This is
// something the needs to be fixed in rustc. There's already drop-tracking, but this is currently
// disabled, see rust-lang/rust#93751. This case isn't picked up by drop-tracking though. If the
// `*guard += 1` is removed it is picked up.
async fn dropped_before_await(x: std::sync::Mutex<u32>) {
let mut guard = x.lock().unwrap();
*guard += 1;
drop(guard);
baz().await;
}
fn main() {
let m = Mutex::new(100);
good(&m);
bad(&m);
also_bad(&m);
not_good(&m);
block_bad(&m);
let m = std::sync::Mutex::new(100);
std_mutex::good(&m);
std_mutex::bad(&m);
std_mutex::also_bad(&m);
std_mutex::not_good(&m);
std_mutex::block_bad(&m);
let m = parking_lot::Mutex::new(100);
parking_lot_mutex::good(&m);
parking_lot_mutex::bad(&m);
parking_lot_mutex::also_bad(&m);
parking_lot_mutex::not_good(&m);
}

View File

@ -1,63 +1,208 @@
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
--> $DIR/await_holding_lock.rs:6:9
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:9:13
|
LL | let guard = x.lock().unwrap();
| ^^^^^
LL | let guard = x.lock().unwrap();
| ^^^^^
|
= note: `-D clippy::await-holding-lock` implied by `-D warnings`
note: these are all the await points this lock is held through
--> $DIR/await_holding_lock.rs:6:5
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
LL | | }
| |_^
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
--> $DIR/await_holding_lock.rs:27:9
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
note: these are all the await points this lock is held through
--> $DIR/await_holding_lock.rs:27:5
|
LL | / let guard = x.lock().unwrap();
LL | |
LL | | let second = baz().await;
LL | |
... |
LL | | first + second + third
LL | | }
| |_^
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
--> $DIR/await_holding_lock.rs:40:13
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
note: these are all the await points this lock is held through
--> $DIR/await_holding_lock.rs:40:9
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
LL | | };
| |_____^
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
--> $DIR/await_holding_lock.rs:52:13
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
note: these are all the await points this lock is held through
--> $DIR/await_holding_lock.rs:52:9
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:9:9
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
LL | | }
| |_____^
error: aborting due to 4 previous errors
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:24:13
|
LL | let guard = x.read().unwrap();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:24:9
|
LL | / let guard = x.read().unwrap();
LL | | baz().await
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:29:13
|
LL | let mut guard = x.write().unwrap();
| ^^^^^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:29:9
|
LL | / let mut guard = x.write().unwrap();
LL | | baz().await
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:50:13
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:50:9
|
LL | / let guard = x.lock().unwrap();
LL | |
LL | | let second = baz().await;
LL | |
... |
LL | | first + second + third
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:63:17
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:63:13
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
LL | | };
| |_________^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:75:17
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:75:13
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
LL | | }
| |_________^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:87:13
|
LL | let guard = x.lock();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:87:9
|
LL | / let guard = x.lock();
LL | | baz().await
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:102:13
|
LL | let guard = x.read();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:102:9
|
LL | / let guard = x.read();
LL | | baz().await
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:107:13
|
LL | let mut guard = x.write();
| ^^^^^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:107:9
|
LL | / let mut guard = x.write();
LL | | baz().await
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:128:13
|
LL | let guard = x.lock();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:128:9
|
LL | / let guard = x.lock();
LL | |
LL | | let second = baz().await;
LL | |
... |
LL | | first + second + third
LL | | }
| |_____^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:141:17
|
LL | let guard = x.lock();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:141:13
|
LL | / let guard = x.lock();
LL | | baz().await
LL | | };
| |_________^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:153:17
|
LL | let guard = x.lock();
| ^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:153:13
|
LL | / let guard = x.lock();
LL | | baz().await
LL | | }
| |_________^
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:173:9
|
LL | let mut guard = x.lock().unwrap();
| ^^^^^^^^^
|
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:173:5
|
LL | / let mut guard = x.lock().unwrap();
LL | | *guard += 1;
LL | | drop(guard);
LL | | baz().await;
LL | | }
| |_^
error: aborting due to 13 previous errors

View File

@ -1,11 +1,12 @@
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:6:9
|
LL | let b = x.borrow();
| ^
|
= note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
note: these are all the await points this ref is held through
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:6:5
|
LL | / let b = x.borrow();
@ -13,13 +14,14 @@ LL | | baz().await
LL | | }
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:11:9
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:11:5
|
LL | / let b = x.borrow_mut();
@ -27,13 +29,14 @@ LL | | baz().await
LL | | }
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:32:9
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:32:5
|
LL | / let b = x.borrow_mut();
@ -45,13 +48,14 @@ LL | | first + second + third
LL | | }
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:44:9
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:44:5
|
LL | / let b = x.borrow_mut();
@ -63,13 +67,14 @@ LL | | first + second + third
LL | | }
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:59:13
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:59:9
|
LL | / let b = x.borrow_mut();
@ -77,13 +82,14 @@ LL | | baz().await
LL | | };
| |_____^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:71:13
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:71:9
|
LL | / let b = x.borrow_mut();