Skip to content

Commit 347c744

Browse files
authored
Rollup merge of #92381 - ThePuzzlemaker:issue-92308, r=estebank
Suggest `return`ing tail expressions in async functions This PR fixes #92308. Previously, the suggestion to `return` tail expressions (introduced in #81769) did not apply to `async` functions, as the suggestion checked whether the types were equal disregarding `impl Future<Output = T>` syntax sugar for `async` functions. This PR changes that in order to fix a potential papercut. I'm not sure if this is the "right" way to do this, so if there is a better way then please let me know. I amended an existing test introduced in #81769 to add a regression test for this, if you think I should make a separate test I will.
2 parents f13e871 + ab7c446 commit 347c744

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_hir as hir;
99
use rustc_hir::def::{CtorOf, DefKind};
1010
use rustc_hir::lang_items::LangItem;
1111
use rustc_hir::{Expr, ExprKind, ItemKind, Node, Path, QPath, Stmt, StmtKind, TyKind};
12-
use rustc_infer::infer;
12+
use rustc_infer::infer::{self, TyCtxtInferExt};
1313
use rustc_middle::lint::in_external_macro;
1414
use rustc_middle::ty::{self, Binder, Ty};
1515
use rustc_span::symbol::{kw, sym};
@@ -608,6 +608,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
608608
let bound_vars = self.tcx.late_bound_vars(fn_id);
609609
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
610610
let ty = self.normalize_associated_types_in(expr.span, ty);
611+
let ty = match self.tcx.asyncness(fn_id.owner) {
612+
hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| {
613+
infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
614+
span_bug!(
615+
fn_decl.output.span(),
616+
"failed to get output type of async function"
617+
)
618+
})
619+
}),
620+
hir::IsAsync::NotAsync => ty,
621+
};
611622
if self.can_coerce(found, ty) {
612623
err.multipart_suggestion(
613624
"you might have meant to return this value",
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
1+
// > Suggest `return`ing tail expressions that match return type
2+
// >
3+
// > Some newcomers are confused by the behavior of tail expressions,
4+
// > interpreting that "leaving out the `;` makes it the return value".
5+
// > To help them go in the right direction, suggest using `return` instead
6+
// > when applicable.
7+
// (original commit description for this test)
8+
//
9+
// This test was amended to also serve as a regression test for #92308, where
10+
// this suggestion would not trigger with async functions.
11+
//
12+
// edition:2018
13+
114
fn main() {
215
let _ = foo(true);
316
}
417

518
fn foo(x: bool) -> Result<f64, i32> {
619
if x {
720
Err(42) //~ ERROR mismatched types
21+
//| HELP you might have meant to return this value
22+
}
23+
Ok(42.0)
24+
}
25+
26+
async fn bar(x: bool) -> Result<f64, i32> {
27+
if x {
28+
Err(42) //~ ERROR mismatched types
29+
//| HELP you might have meant to return this value
830
}
931
Ok(42.0)
1032
}

src/test/ui/return/tail-expr-as-potential-return.stderr

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
error[E0308]: mismatched types
2-
--> $DIR/tail-expr-as-potential-return.rs:7:9
2+
--> $DIR/tail-expr-as-potential-return.rs:28:9
33
|
44
LL | / if x {
55
LL | | Err(42)
66
| | ^^^^^^^ expected `()`, found enum `Result`
7+
LL | | //| HELP you might have meant to return this value
78
LL | | }
89
| |_____- expected this to be `()`
910
|
@@ -14,6 +15,23 @@ help: you might have meant to return this value
1415
LL | return Err(42);
1516
| ++++++ +
1617

17-
error: aborting due to previous error
18+
error[E0308]: mismatched types
19+
--> $DIR/tail-expr-as-potential-return.rs:20:9
20+
|
21+
LL | / if x {
22+
LL | | Err(42)
23+
| | ^^^^^^^ expected `()`, found enum `Result`
24+
LL | | //| HELP you might have meant to return this value
25+
LL | | }
26+
| |_____- expected this to be `()`
27+
|
28+
= note: expected unit type `()`
29+
found enum `Result<_, {integer}>`
30+
help: you might have meant to return this value
31+
|
32+
LL | return Err(42);
33+
| ++++++ +
34+
35+
error: aborting due to 2 previous errors
1836

1937
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)