Skip to content

Commit 88dc123

Browse files
committed
Fix implicit_return suggestion for async functions
1 parent 822c37d commit 88dc123

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, CrateItem, Expr, ExprKind, FieldDef, FnDecl, ForeignItem,
64-
GenericArgs, GenericParam, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, LangItem, Lifetime, Local,
64+
GenericArgs, GenericParam, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Lifetime, Local,
6565
MacroDef, MatchSource, Node, Param, Pat, PatKind, Path, PathSegment, QPath, Stmt, TraitItem, TraitItemKind,
6666
TraitRef, TyKind, Variant, Visibility,
6767
};
@@ -1231,6 +1231,40 @@ pub fn parent_node_is_if_expr(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
12311231
)
12321232
}
12331233

1234+
/// Checks if the given function kind is an async function.
1235+
pub fn is_async_fn(kind: FnKind) -> bool {
1236+
matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
1237+
}
1238+
1239+
/// Peels away all the compiler generated code surrounding the body of an async function,
1240+
pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
1241+
if let ExprKind::Call(
1242+
_,
1243+
&[Expr {
1244+
kind: ExprKind::Closure(_, _, body, _, _),
1245+
..
1246+
}],
1247+
) = body.value.kind
1248+
{
1249+
if let ExprKind::Block(
1250+
Block {
1251+
stmts: [],
1252+
expr:
1253+
Some(Expr {
1254+
kind: ExprKind::DropTemps(expr),
1255+
..
1256+
}),
1257+
..
1258+
},
1259+
_,
1260+
) = tcx.hir().body(body).value.kind
1261+
{
1262+
return Some(expr);
1263+
}
1264+
};
1265+
None
1266+
}
1267+
12341268
// Finds the attribute with the given name, if any
12351269
pub fn attr_by_name<'a>(attrs: &'a [Attribute], name: &'_ str) -> Option<&'a Attribute> {
12361270
attrs

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)