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:
Eduardo Broto 2020-08-03 00:36:28 +02:00
parent 2e0f8b6cc6
commit e336fe80d2
6 changed files with 146 additions and 40 deletions

View file

@ -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();

View file

@ -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

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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