manual_async_fn: take input lifetimes into account
The anonymous future returned from an `async fn` captures all input lifetimes. This was not being taken into account. See https://github.com/rust-lang/rfcs/blob/master/text/2394-async_await.md#lifetime-capture-in-the-anonymous-future
This commit is contained in:
parent
2e0f8b6cc6
commit
e336fe80d2
6 changed files with 146 additions and 40 deletions
|
|
@ -47,6 +47,7 @@ async fn not_good(x: &Mutex<u32>) -> u32 {
|
|||
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();
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ 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
|
||||
--> $DIR/await_holding_lock.rs:53: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
|
||||
--> $DIR/await_holding_lock.rs:53:9
|
||||
|
|
||||
LL | / let guard = x.lock().unwrap();
|
||||
LL | | baz().await
|
||||
|
|
|
|||
|
|
@ -43,10 +43,6 @@ impl S {
|
|||
42
|
||||
}
|
||||
|
||||
async fn meth_fut(&self) -> i32 { 42 }
|
||||
|
||||
async fn empty_fut(&self) {}
|
||||
|
||||
// should be ignored
|
||||
fn not_fut(&self) -> i32 {
|
||||
42
|
||||
|
|
@ -64,4 +60,40 @@ impl S {
|
|||
}
|
||||
}
|
||||
|
||||
// Tests related to lifetime capture
|
||||
|
||||
async fn elided(_: &i32) -> i32 { 42 }
|
||||
|
||||
// should be ignored
|
||||
fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 }
|
||||
|
||||
// should be ignored
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
// should be ignored
|
||||
mod issue_5765 {
|
||||
use std::future::Future;
|
||||
|
||||
struct A;
|
||||
impl A {
|
||||
fn f(&self) -> impl Future<Output = ()> {
|
||||
async {}
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let _future = {
|
||||
let a = A;
|
||||
a.f()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -51,14 +51,6 @@ impl S {
|
|||
}
|
||||
}
|
||||
|
||||
fn meth_fut(&self) -> impl Future<Output = i32> {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
fn empty_fut(&self) -> impl Future<Output = ()> {
|
||||
async {}
|
||||
}
|
||||
|
||||
// should be ignored
|
||||
fn not_fut(&self) -> i32 {
|
||||
42
|
||||
|
|
@ -76,4 +68,44 @@ impl S {
|
|||
}
|
||||
}
|
||||
|
||||
// Tests related to lifetime capture
|
||||
|
||||
fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
// should be ignored
|
||||
fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
// should be ignored
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
// should be ignored
|
||||
mod issue_5765 {
|
||||
use std::future::Future;
|
||||
|
||||
struct A;
|
||||
impl A {
|
||||
fn f(&self) -> impl Future<Output = ()> {
|
||||
async {}
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let _future = {
|
||||
let a = A;
|
||||
a.f()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -65,34 +65,34 @@ LL | let c = 21;
|
|||
...
|
||||
|
||||
error: this function can be simplified using the `async fn` syntax
|
||||
--> $DIR/manual_async_fn.rs:54:5
|
||||
--> $DIR/manual_async_fn.rs:73:1
|
||||
|
|
||||
LL | fn meth_fut(&self) -> impl Future<Output = i32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `async` and return the output of the future directly
|
||||
|
|
||||
LL | async fn meth_fut(&self) -> i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | async fn elided(_: &i32) -> i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: move the body of the async block to the enclosing function
|
||||
|
|
||||
LL | fn meth_fut(&self) -> impl Future<Output = i32> { 42 }
|
||||
| ^^^^^^
|
||||
LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 }
|
||||
| ^^^^^^
|
||||
|
||||
error: this function can be simplified using the `async fn` syntax
|
||||
--> $DIR/manual_async_fn.rs:58:5
|
||||
--> $DIR/manual_async_fn.rs:82:1
|
||||
|
|
||||
LL | fn empty_fut(&self) -> impl Future<Output = ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `async` and remove the return type
|
||||
help: make the function `async` and return the output of the future directly
|
||||
|
|
||||
LL | async fn empty_fut(&self) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: move the body of the async block to the enclosing function
|
||||
|
|
||||
LL | fn empty_fut(&self) -> impl Future<Output = ()> {}
|
||||
| ^^
|
||||
LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b { 42 }
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue