Skip to content

Commit 2b85fc1

Browse files
committed
implicit_return: do not suggest adding return into desugared code
Blocks created by desugaring will not contain an explicit `return`. Do not suggest to add it when the user has no control over the desugared code. Also, in the case of an implicit return on a `.await` expression, ensure that the suggested `return` is emitted at the right place instead of before the `await` keyword.
1 parent 9a1e7c5 commit 2b85fc1

File tree

4 files changed

+182
-2
lines changed

4 files changed

+182
-2
lines changed

clippy_lints/src/implicit_return.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_hir_and_then;
22
use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context};
33
use clippy_utils::visitors::for_each_expr_without_closures;
4-
use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
4+
use clippy_utils::{desugar_await, get_async_closure_expr, get_async_fn_body, is_async_fn, is_from_proc_macro};
55
use core::ops::ControlFlow;
66
use rustc_errors::Applicability;
77
use rustc_hir::intravisit::FnKind;
@@ -134,6 +134,10 @@ fn lint_implicit_returns(
134134
},
135135

136136
ExprKind::Match(_, arms, _) => {
137+
if let Some(await_expr) = desugar_await(expr) {
138+
lint_return(cx, await_expr.hir_id, await_expr.span);
139+
return LintLocation::Inner;
140+
}
137141
for arm in arms {
138142
let res = lint_implicit_returns(
139143
cx,
@@ -241,6 +245,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn {
241245
Some(e) => e,
242246
None => return,
243247
}
248+
} else if let Some(expr) = get_async_closure_expr(cx.tcx, body.value) {
249+
expr
244250
} else {
245251
body.value
246252
};

tests/ui/implicit_return.fixed

+43
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,46 @@ with_span!(
165165
x
166166
}
167167
);
168+
169+
fn desugared_closure_14446() {
170+
let _ = async || return 0;
171+
//~^ implicit_return
172+
#[rustfmt::skip]
173+
let _ = async || -> i32 { return 0 };
174+
//~^ implicit_return
175+
let _ = async |a: i32| return a;
176+
//~^ implicit_return
177+
#[rustfmt::skip]
178+
let _ = async |a: i32| { return a };
179+
//~^ implicit_return
180+
181+
let _ = async || return 0;
182+
let _ = async || -> i32 { return 0 };
183+
let _ = async |a: i32| return a;
184+
#[rustfmt::skip]
185+
let _ = async |a: i32| { return a; };
186+
187+
let _ = async || return foo().await;
188+
//~^ implicit_return
189+
let _ = async || {
190+
foo().await;
191+
return foo().await
192+
};
193+
//~^^ implicit_return
194+
#[rustfmt::skip]
195+
let _ = async || { return foo().await };
196+
//~^ implicit_return
197+
let _ = async || -> bool { return foo().await };
198+
//~^ implicit_return
199+
200+
let _ = async || return foo().await;
201+
let _ = async || {
202+
foo().await;
203+
return foo().await;
204+
};
205+
#[rustfmt::skip]
206+
let _ = async || { return foo().await; };
207+
let _ = async || -> bool {
208+
return foo().await;
209+
};
210+
}

tests/ui/implicit_return.rs

+43
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,46 @@ with_span!(
165165
x
166166
}
167167
);
168+
169+
fn desugared_closure_14446() {
170+
let _ = async || 0;
171+
//~^ implicit_return
172+
#[rustfmt::skip]
173+
let _ = async || -> i32 { 0 };
174+
//~^ implicit_return
175+
let _ = async |a: i32| a;
176+
//~^ implicit_return
177+
#[rustfmt::skip]
178+
let _ = async |a: i32| { a };
179+
//~^ implicit_return
180+
181+
let _ = async || return 0;
182+
let _ = async || -> i32 { return 0 };
183+
let _ = async |a: i32| return a;
184+
#[rustfmt::skip]
185+
let _ = async |a: i32| { return a; };
186+
187+
let _ = async || foo().await;
188+
//~^ implicit_return
189+
let _ = async || {
190+
foo().await;
191+
foo().await
192+
};
193+
//~^^ implicit_return
194+
#[rustfmt::skip]
195+
let _ = async || { foo().await };
196+
//~^ implicit_return
197+
let _ = async || -> bool { foo().await };
198+
//~^ implicit_return
199+
200+
let _ = async || return foo().await;
201+
let _ = async || {
202+
foo().await;
203+
return foo().await;
204+
};
205+
#[rustfmt::skip]
206+
let _ = async || { return foo().await; };
207+
let _ = async || -> bool {
208+
return foo().await;
209+
};
210+
}

tests/ui/implicit_return.stderr

+89-1
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,93 @@ help: add `return` as shown
183183
LL | return true
184184
| ++++++
185185

186-
error: aborting due to 16 previous errors
186+
error: missing `return` statement
187+
--> tests/ui/implicit_return.rs:170:22
188+
|
189+
LL | let _ = async || 0;
190+
| ^
191+
|
192+
help: add `return` as shown
193+
|
194+
LL | let _ = async || return 0;
195+
| ++++++
196+
197+
error: missing `return` statement
198+
--> tests/ui/implicit_return.rs:173:31
199+
|
200+
LL | let _ = async || -> i32 { 0 };
201+
| ^
202+
|
203+
help: add `return` as shown
204+
|
205+
LL | let _ = async || -> i32 { return 0 };
206+
| ++++++
207+
208+
error: missing `return` statement
209+
--> tests/ui/implicit_return.rs:175:28
210+
|
211+
LL | let _ = async |a: i32| a;
212+
| ^
213+
|
214+
help: add `return` as shown
215+
|
216+
LL | let _ = async |a: i32| return a;
217+
| ++++++
218+
219+
error: missing `return` statement
220+
--> tests/ui/implicit_return.rs:178:30
221+
|
222+
LL | let _ = async |a: i32| { a };
223+
| ^
224+
|
225+
help: add `return` as shown
226+
|
227+
LL | let _ = async |a: i32| { return a };
228+
| ++++++
229+
230+
error: missing `return` statement
231+
--> tests/ui/implicit_return.rs:187:22
232+
|
233+
LL | let _ = async || foo().await;
234+
| ^^^^^
235+
|
236+
help: add `return` as shown
237+
|
238+
LL | let _ = async || return foo().await;
239+
| ++++++
240+
241+
error: missing `return` statement
242+
--> tests/ui/implicit_return.rs:191:9
243+
|
244+
LL | foo().await
245+
| ^^^^^
246+
|
247+
help: add `return` as shown
248+
|
249+
LL | return foo().await
250+
| ++++++
251+
252+
error: missing `return` statement
253+
--> tests/ui/implicit_return.rs:195:24
254+
|
255+
LL | let _ = async || { foo().await };
256+
| ^^^^^
257+
|
258+
help: add `return` as shown
259+
|
260+
LL | let _ = async || { return foo().await };
261+
| ++++++
262+
263+
error: missing `return` statement
264+
--> tests/ui/implicit_return.rs:197:32
265+
|
266+
LL | let _ = async || -> bool { foo().await };
267+
| ^^^^^
268+
|
269+
help: add `return` as shown
270+
|
271+
LL | let _ = async || -> bool { return foo().await };
272+
| ++++++
273+
274+
error: aborting due to 24 previous errors
187275

0 commit comments

Comments
 (0)