Skip to content

Commit 984422a

Browse files
committed
Add new redundant_async_block lint
1 parent 113c704 commit 984422a

13 files changed

+175
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4834,6 +4834,7 @@ Released 2018-09-13
48344834
[`read_zero_byte_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#read_zero_byte_vec
48354835
[`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl
48364836
[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
4837+
[`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_async_block
48374838
[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
48384839
[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
48394840
[`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
517517
crate::ranges::REVERSED_EMPTY_RANGES_INFO,
518518
crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO,
519519
crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO,
520+
crate::redundant_async_block::REDUNDANT_ASYNC_BLOCK_INFO,
520521
crate::redundant_clone::REDUNDANT_CLONE_INFO,
521522
crate::redundant_closure_call::REDUNDANT_CLOSURE_CALL_INFO,
522523
crate::redundant_else::REDUNDANT_ELSE_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ mod question_mark_used;
249249
mod ranges;
250250
mod rc_clone_in_vec_init;
251251
mod read_zero_byte_vec;
252+
mod redundant_async_block;
252253
mod redundant_clone;
253254
mod redundant_closure_call;
254255
mod redundant_else;
@@ -924,6 +925,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
924925
))
925926
});
926927
store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
928+
store.register_early_pass(|| Box::new(redundant_async_block::RedundantAsyncBlock));
927929
// add lints here, do not remove this comment, it's used in `new_lint`
928930
}
929931

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet};
2+
use rustc_ast::ast::*;
3+
use rustc_errors::Applicability;
4+
use rustc_lint::{EarlyContext, EarlyLintPass};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
/// Checks for `async` block that only returns `await` on a future.
10+
///
11+
/// ### Why is this bad?
12+
/// It is shorter to directly use the future.
13+
///
14+
/// ### Example
15+
/// ```rust
16+
/// await {
17+
/// function_returning_a_future().await
18+
/// }
19+
/// ```
20+
/// Use instead:
21+
/// ```rust
22+
/// function_returning_a_future()
23+
/// ```
24+
#[clippy::version = "1.69.0"]
25+
pub REDUNDANT_ASYNC_BLOCK,
26+
complexity,
27+
"`async { future.await }` can be replaced by `future`"
28+
}
29+
declare_lint_pass!(RedundantAsyncBlock => [REDUNDANT_ASYNC_BLOCK]);
30+
31+
impl EarlyLintPass for RedundantAsyncBlock {
32+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &rustc_ast::Expr) {
33+
if expr.span.from_expansion() {
34+
return;
35+
}
36+
if let ExprKind::Async(_, _, block) = &expr.kind && block.stmts.len() == 1 &&
37+
let Some(Stmt { kind: StmtKind::Expr(last), .. }) = block.stmts.last() &&
38+
let ExprKind::Await(future) = &last.kind
39+
{
40+
span_lint_and_sugg(
41+
cx,
42+
REDUNDANT_ASYNC_BLOCK,
43+
expr.span,
44+
"this async-await expression is equivalent to the future itself",
45+
"you can reduce it to",
46+
snippet(cx, future.span, "..").into_owned(),
47+
Applicability::MachineApplicable,
48+
);
49+
}
50+
}
51+
}

tests/ui/async_yields_async.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(lint_reasons)]
33
#![feature(async_closure)]
44
#![warn(clippy::async_yields_async)]
5+
#![allow(clippy::redundant_async_block)]
56

67
use core::future::Future;
78
use core::pin::Pin;

tests/ui/async_yields_async.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(lint_reasons)]
33
#![feature(async_closure)]
44
#![warn(clippy::async_yields_async)]
5+
#![allow(clippy::redundant_async_block)]
56

67
use core::future::Future;
78
use core::pin::Pin;

tests/ui/async_yields_async.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: an async construct yields a type which is itself awaitable
2-
--> $DIR/async_yields_async.rs:39:9
2+
--> $DIR/async_yields_async.rs:40:9
33
|
44
LL | let _h = async {
55
| _____________________-
@@ -19,7 +19,7 @@ LL + }.await
1919
|
2020

2121
error: an async construct yields a type which is itself awaitable
22-
--> $DIR/async_yields_async.rs:44:9
22+
--> $DIR/async_yields_async.rs:45:9
2323
|
2424
LL | let _i = async {
2525
| ____________________-
@@ -32,7 +32,7 @@ LL | | };
3232
| |_____- outer async construct
3333

3434
error: an async construct yields a type which is itself awaitable
35-
--> $DIR/async_yields_async.rs:50:9
35+
--> $DIR/async_yields_async.rs:51:9
3636
|
3737
LL | let _j = async || {
3838
| ________________________-
@@ -51,7 +51,7 @@ LL + }.await
5151
|
5252

5353
error: an async construct yields a type which is itself awaitable
54-
--> $DIR/async_yields_async.rs:55:9
54+
--> $DIR/async_yields_async.rs:56:9
5555
|
5656
LL | let _k = async || {
5757
| _______________________-
@@ -64,7 +64,7 @@ LL | | };
6464
| |_____- outer async construct
6565

6666
error: an async construct yields a type which is itself awaitable
67-
--> $DIR/async_yields_async.rs:57:23
67+
--> $DIR/async_yields_async.rs:58:23
6868
|
6969
LL | let _l = async || CustomFutureType;
7070
| ^^^^^^^^^^^^^^^^
@@ -74,7 +74,7 @@ LL | let _l = async || CustomFutureType;
7474
| help: consider awaiting this value: `CustomFutureType.await`
7575

7676
error: an async construct yields a type which is itself awaitable
77-
--> $DIR/async_yields_async.rs:63:9
77+
--> $DIR/async_yields_async.rs:64:9
7878
|
7979
LL | let _m = async || {
8080
| _______________________-

tests/ui/redundant_async_block.fixed

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// run-rustfix
2+
3+
#![allow(unused)]
4+
#![warn(clippy::redundant_async_block)]
5+
6+
use std::ops::Deref;
7+
async fn foo() -> u32 {
8+
42
9+
}
10+
11+
async fn bar() -> String {
12+
let s = String::from("some string");
13+
let f = async { s.deref().to_owned() };
14+
let x = f;
15+
x.await
16+
}
17+
18+
fn main() {
19+
let fut1 = async { 42 };
20+
let fut2 = fut1;
21+
22+
let fut1 = async { 42 };
23+
let fut2 = fut1;
24+
25+
let fut = async { 42 };
26+
27+
// Do not lint: not a single expression
28+
let fut = async {
29+
foo().await;
30+
foo().await
31+
};
32+
}

tests/ui/redundant_async_block.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
#![allow(unused)]
4+
#![warn(clippy::redundant_async_block)]
5+
6+
async fn foo() -> u32 {
7+
42
8+
}
9+
10+
async fn bar() -> String {
11+
let s = String::from("some string");
12+
let f = async { s.deref().to_owned() };
13+
let x = async { f.await };
14+
x.await
15+
}
16+
17+
fn main() {
18+
let fut1 = async { 42 };
19+
let fut2 = async { fut1.await };
20+
21+
let fut1 = async { 42 };
22+
let fut2 = async move { fut1.await };
23+
24+
let fut = async { async { 42 }.await };
25+
26+
// Do not lint: not a single expression
27+
let fut = async {
28+
foo().await;
29+
foo().await
30+
};
31+
}

tests/ui/redundant_async_block.stderr

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error: this async-await expression is equivalent to the future
2+
--> $DIR/redundant_async_block.rs:13:13
3+
|
4+
LL | let x = async { f.await };
5+
| ^^^^^^^^^^^^^^^^^ help: you can reduce it to: `f`
6+
|
7+
= note: `-D clippy::redundant-async-block` implied by `-D warnings`
8+
9+
error: this async-await expression is equivalent to the future
10+
--> $DIR/redundant_async_block.rs:19:16
11+
|
12+
LL | let fut2 = async { fut1.await };
13+
| ^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1`
14+
15+
error: this async-await expression is equivalent to the future
16+
--> $DIR/redundant_async_block.rs:22:16
17+
|
18+
LL | let fut2 = async move { fut1.await };
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1`
20+
21+
error: this async-await expression is equivalent to the future
22+
--> $DIR/redundant_async_block.rs:24:15
23+
|
24+
LL | let fut = async { async { 42 }.await };
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }`
26+
27+
error[E0599]: no method named `deref` found for struct `std::string::String` in the current scope
28+
--> $DIR/redundant_async_block.rs:12:23
29+
|
30+
LL | let f = async { s.deref().to_owned() };
31+
| ^^^^^ method not found in `String`
32+
|
33+
= help: items from traits can only be used if the trait is in scope
34+
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
35+
|
36+
LL | use std::ops::Deref;
37+
|
38+
39+
error: aborting due to 5 previous errors
40+
41+
For more information about this error, try `rustc --explain E0599`.

tests/ui/redundant_closure_call_fixable.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![feature(async_closure)]
44
#![warn(clippy::redundant_closure_call)]
5+
#![allow(clippy::redundant_async_block)]
56
#![allow(unused)]
67

78
async fn something() -> u32 {

tests/ui/redundant_closure_call_fixable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![feature(async_closure)]
44
#![warn(clippy::redundant_closure_call)]
5+
#![allow(clippy::redundant_async_block)]
56
#![allow(unused)]
67

78
async fn something() -> u32 {

tests/ui/redundant_closure_call_fixable.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: try not to call a closure in the expression where it is declared
2-
--> $DIR/redundant_closure_call_fixable.rs:16:13
2+
--> $DIR/redundant_closure_call_fixable.rs:17:13
33
|
44
LL | let a = (|| 42)();
55
| ^^^^^^^^^ help: try doing something like: `42`
66
|
77
= note: `-D clippy::redundant-closure-call` implied by `-D warnings`
88

99
error: try not to call a closure in the expression where it is declared
10-
--> $DIR/redundant_closure_call_fixable.rs:17:13
10+
--> $DIR/redundant_closure_call_fixable.rs:18:13
1111
|
1212
LL | let b = (async || {
1313
| _____________^
@@ -27,7 +27,7 @@ LL ~ };
2727
|
2828

2929
error: try not to call a closure in the expression where it is declared
30-
--> $DIR/redundant_closure_call_fixable.rs:22:13
30+
--> $DIR/redundant_closure_call_fixable.rs:23:13
3131
|
3232
LL | let c = (|| {
3333
| _____________^
@@ -47,13 +47,13 @@ LL ~ };
4747
|
4848

4949
error: try not to call a closure in the expression where it is declared
50-
--> $DIR/redundant_closure_call_fixable.rs:27:13
50+
--> $DIR/redundant_closure_call_fixable.rs:28:13
5151
|
5252
LL | let d = (async || something().await)();
5353
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
5454

5555
error: try not to call a closure in the expression where it is declared
56-
--> $DIR/redundant_closure_call_fixable.rs:36:13
56+
--> $DIR/redundant_closure_call_fixable.rs:37:13
5757
|
5858
LL | (|| m!())()
5959
| ^^^^^^^^^^^ help: try doing something like: `m!()`
@@ -64,7 +64,7 @@ LL | m2!();
6464
= note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
6565

6666
error: try not to call a closure in the expression where it is declared
67-
--> $DIR/redundant_closure_call_fixable.rs:31:13
67+
--> $DIR/redundant_closure_call_fixable.rs:32:13
6868
|
6969
LL | (|| 0)()
7070
| ^^^^^^^^ help: try doing something like: `0`

0 commit comments

Comments
 (0)