Skip to content

Commit a7ddaf6

Browse files
committed
Fix implicit_return suggestion for async functions
1 parent 065f94b commit a7ddaf6

File tree

5 files changed

+80
-19
lines changed

5 files changed

+80
-19
lines changed

clippy_lints/src/implicit_return.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use clippy_utils::{
22
diagnostics::span_lint_and_sugg,
3+
get_async_fn_body, is_async_fn,
34
source::{snippet_with_applicability, snippet_with_context, walk_span_to_context},
45
visitors::visit_break_exprs,
56
};
@@ -219,6 +220,14 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn {
219220
return;
220221
}
221222

222-
lint_implicit_returns(cx, &body.value, body.value.span.ctxt(), None);
223+
let expr = if is_async_fn(kind) {
224+
match get_async_fn_body(cx.tcx, body) {
225+
Some(e) => e,
226+
None => return,
227+
}
228+
} else {
229+
&body.value
230+
};
231+
lint_implicit_returns(cx, expr, expr.span.ctxt(), None);
223232
}
224233
}

clippy_utils/src/lib.rs

+36-2
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ use rustc_data_structures::fx::FxHashMap;
5858
use rustc_hir as hir;
5959
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
6060
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
61-
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
61+
use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor};
6262
use rustc_hir::{
6363
def, Arm, BindingAnnotation, Block, Body, Constness, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, ImplItem,
64-
ImplItemKind, Item, ItemKind, LangItem, MatchSource, Node, Param, Pat, PatKind, Path, PathSegment, QPath,
64+
ImplItemKind, IsAsync, Item, ItemKind, LangItem, MatchSource, Node, Param, Pat, PatKind, Path, PathSegment, QPath,
6565
TraitItem, TraitItemKind, TraitRef, TyKind,
6666
};
6767
use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -1203,6 +1203,40 @@ pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
12031203
)
12041204
}
12051205

1206+
/// Checks if the given function kind is an async function.
1207+
pub fn is_async_fn(kind: FnKind) -> bool {
1208+
matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
1209+
}
1210+
1211+
/// Peels away all the compiler generated code surrounding the body of an async function,
1212+
pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
1213+
if let ExprKind::Call(
1214+
_,
1215+
&[Expr {
1216+
kind: ExprKind::Closure(_, _, body, _, _),
1217+
..
1218+
}],
1219+
) = body.value.kind
1220+
{
1221+
if let ExprKind::Block(
1222+
Block {
1223+
stmts: [],
1224+
expr:
1225+
Some(Expr {
1226+
kind: ExprKind::DropTemps(expr),
1227+
..
1228+
}),
1229+
..
1230+
},
1231+
_,
1232+
) = tcx.hir().body(body).value.kind
1233+
{
1234+
return Some(expr);
1235+
}
1236+
};
1237+
None
1238+
}
1239+
12061240
// Finds the `#[must_use]` attribute, if any
12071241
pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
12081242
attrs.iter().find(|a| a.has_name(sym::must_use))

tests/ui/implicit_return.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// edition:2018
12
// run-rustfix
23

34
#![warn(clippy::implicit_return)]
@@ -122,4 +123,9 @@ fn divergent_test() -> bool {
122123
diverge()
123124
}
124125

126+
// issue #6940
127+
async fn foo() -> bool {
128+
return true
129+
}
130+
125131
fn main() {}

tests/ui/implicit_return.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// edition:2018
12
// run-rustfix
23

34
#![warn(clippy::implicit_return)]
@@ -122,4 +123,9 @@ fn divergent_test() -> bool {
122123
diverge()
123124
}
124125

126+
// issue #6940
127+
async fn foo() -> bool {
128+
true
129+
}
130+
125131
fn main() {}

tests/ui/implicit_return.stderr

+22-16
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,91 @@
11
error: missing `return` statement
2-
--> $DIR/implicit_return.rs:12:5
2+
--> $DIR/implicit_return.rs:13:5
33
|
44
LL | true
55
| ^^^^ help: add `return` as shown: `return true`
66
|
77
= note: `-D clippy::implicit-return` implied by `-D warnings`
88

99
error: missing `return` statement
10-
--> $DIR/implicit_return.rs:16:15
10+
--> $DIR/implicit_return.rs:17:15
1111
|
1212
LL | if true { true } else { false }
1313
| ^^^^ help: add `return` as shown: `return true`
1414

1515
error: missing `return` statement
16-
--> $DIR/implicit_return.rs:16:29
16+
--> $DIR/implicit_return.rs:17:29
1717
|
1818
LL | if true { true } else { false }
1919
| ^^^^^ help: add `return` as shown: `return false`
2020

2121
error: missing `return` statement
22-
--> $DIR/implicit_return.rs:22:17
22+
--> $DIR/implicit_return.rs:23:17
2323
|
2424
LL | true => false,
2525
| ^^^^^ help: add `return` as shown: `return false`
2626

2727
error: missing `return` statement
28-
--> $DIR/implicit_return.rs:23:20
28+
--> $DIR/implicit_return.rs:24:20
2929
|
3030
LL | false => { true },
3131
| ^^^^ help: add `return` as shown: `return true`
3232

3333
error: missing `return` statement
34-
--> $DIR/implicit_return.rs:36:9
34+
--> $DIR/implicit_return.rs:37:9
3535
|
3636
LL | break true;
3737
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
3838

3939
error: missing `return` statement
40-
--> $DIR/implicit_return.rs:43:13
40+
--> $DIR/implicit_return.rs:44:13
4141
|
4242
LL | break true;
4343
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
4444

4545
error: missing `return` statement
46-
--> $DIR/implicit_return.rs:51:13
46+
--> $DIR/implicit_return.rs:52:13
4747
|
4848
LL | break true;
4949
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
5050

5151
error: missing `return` statement
52-
--> $DIR/implicit_return.rs:69:18
52+
--> $DIR/implicit_return.rs:70:18
5353
|
5454
LL | let _ = || { true };
5555
| ^^^^ help: add `return` as shown: `return true`
5656

5757
error: missing `return` statement
58-
--> $DIR/implicit_return.rs:70:16
58+
--> $DIR/implicit_return.rs:71:16
5959
|
6060
LL | let _ = || true;
6161
| ^^^^ help: add `return` as shown: `return true`
6262

6363
error: missing `return` statement
64-
--> $DIR/implicit_return.rs:78:5
64+
--> $DIR/implicit_return.rs:79:5
6565
|
6666
LL | format!("test {}", "test")
6767
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")`
6868

6969
error: missing `return` statement
70-
--> $DIR/implicit_return.rs:87:5
70+
--> $DIR/implicit_return.rs:88:5
7171
|
7272
LL | m!(true, false)
7373
| ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)`
7474

7575
error: missing `return` statement
76-
--> $DIR/implicit_return.rs:93:13
76+
--> $DIR/implicit_return.rs:94:13
7777
|
7878
LL | break true;
7979
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
8080

8181
error: missing `return` statement
82-
--> $DIR/implicit_return.rs:98:17
82+
--> $DIR/implicit_return.rs:99:17
8383
|
8484
LL | break 'outer false;
8585
| ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false`
8686

8787
error: missing `return` statement
88-
--> $DIR/implicit_return.rs:113:5
88+
--> $DIR/implicit_return.rs:114:5
8989
|
9090
LL | / loop {
9191
LL | | m!(true);
@@ -99,5 +99,11 @@ LL | m!(true);
9999
LL | }
100100
|
101101

102-
error: aborting due to 15 previous errors
102+
error: missing `return` statement
103+
--> $DIR/implicit_return.rs:128:5
104+
|
105+
LL | true
106+
| ^^^^ help: add `return` as shown: `return true`
107+
108+
error: aborting due to 16 previous errors
103109

0 commit comments

Comments
 (0)