In some situations, such as async-aware Mutexes, it is useful to call an async function and bind its result to a variable so that it drops at the end of the scope - e.g. let _guard = mutex.lock().await. However, it's probably a mistake to do so without awaiting (or block_on, or otherwise consuming) the Future.
This is a bit rare as you'd usually notice when making use of the returned guard, but not always. This came up today and was a real head-scratcher.
Lint Name
No response
Category
correctness
Advantage
This lint detects an issue that is completely silent at compile time, and hard to detect in tests. (In the mutex example, casual testing may not discover the lack of mutual exclusion at all!)
Drawbacks
This could cause a false positive when calling a (non-async) function that returns a type that implements Future but also has its own nontrivial Drop implementation, that the caller intentionally wants to defer. I'm not aware of any use case where that would apply. In particular, this never applies to an async fn as dropping an async block does nothing except drop its captured arguments.
What it does
In some situations, such as async-aware Mutexes, it is useful to call an async function and bind its result to a variable so that it drops at the end of the scope - e.g.
let _guard = mutex.lock().await
. However, it's probably a mistake to do so without awaiting (orblock_on
, or otherwise consuming) the Future.This is a bit rare as you'd usually notice when making use of the returned guard, but not always. This came up today and was a real head-scratcher.
Lint Name
No response
Category
correctness
Advantage
This lint detects an issue that is completely silent at compile time, and hard to detect in tests. (In the mutex example, casual testing may not discover the lack of mutual exclusion at all!)
Drawbacks
This could cause a false positive when calling a (non-
async
) function that returns a type that implementsFuture
but also has its own nontrivialDrop
implementation, that the caller intentionally wants to defer. I'm not aware of any use case where that would apply. In particular, this never applies to anasync fn
as dropping anasync
block does nothing except drop its captured arguments.Example
Should be instead: