about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-01-14 07:47:32 +0100
committerGitHub <noreply@github.com>2022-01-14 07:47:32 +0100
commit347c744fe0e464737dbbdc44d148c84fc07568cb (patch)
tree14030d488ca3fccf39bff1c20f3d22807c828211
parentf13e871ac561b54ddeac2b6173b1905fb4b20138 (diff)
parentab7c4464920531559c4da0a9e9b8972ae2443ed1 (diff)
downloadrust-347c744fe0e464737dbbdc44d148c84fc07568cb.tar.gz
rust-347c744fe0e464737dbbdc44d148c84fc07568cb.zip
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.
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs13
-rw-r--r--src/test/ui/return/tail-expr-as-potential-return.rs22
-rw-r--r--src/test/ui/return/tail-expr-as-potential-return.stderr22
3 files changed, 54 insertions, 3 deletions
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 6c7d3a0c9c0..e8a0cc946b5 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -9,7 +9,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Expr, ExprKind, ItemKind, Node, Path, QPath, Stmt, StmtKind, TyKind};
-use rustc_infer::infer;
+use rustc_infer::infer::{self, TyCtxtInferExt};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Binder, Ty};
 use rustc_span::symbol::{kw, sym};
@@ -608,6 +608,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let bound_vars = self.tcx.late_bound_vars(fn_id);
             let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
             let ty = self.normalize_associated_types_in(expr.span, ty);
+            let ty = match self.tcx.asyncness(fn_id.owner) {
+                hir::IsAsync::Async => self.tcx.infer_ctxt().enter(|infcx| {
+                    infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
+                        span_bug!(
+                            fn_decl.output.span(),
+                            "failed to get output type of async function"
+                        )
+                    })
+                }),
+                hir::IsAsync::NotAsync => ty,
+            };
             if self.can_coerce(found, ty) {
                 err.multipart_suggestion(
                     "you might have meant to return this value",
diff --git a/src/test/ui/return/tail-expr-as-potential-return.rs b/src/test/ui/return/tail-expr-as-potential-return.rs
index 83266abfa06..2c3610fb24d 100644
--- a/src/test/ui/return/tail-expr-as-potential-return.rs
+++ b/src/test/ui/return/tail-expr-as-potential-return.rs
@@ -1,3 +1,16 @@
+// > Suggest `return`ing tail expressions that match return type
+// >
+// > Some newcomers are confused by the behavior of tail expressions,
+// > interpreting that "leaving out the `;` makes it the return value".
+// > To help them go in the right direction, suggest using `return` instead
+// > when applicable.
+// (original commit description for this test)
+//
+// This test was amended to also serve as a regression test for #92308, where
+// this suggestion would not trigger with async functions.
+//
+// edition:2018
+
 fn main() {
     let _ = foo(true);
 }
@@ -5,6 +18,15 @@ fn main() {
 fn foo(x: bool) -> Result<f64, i32> {
     if x {
         Err(42) //~ ERROR mismatched types
+                //| HELP you might have meant to return this value
+    }
+    Ok(42.0)
+}
+
+async fn bar(x: bool) -> Result<f64, i32> {
+    if x {
+        Err(42) //~ ERROR mismatched types
+                //| HELP you might have meant to return this value
     }
     Ok(42.0)
 }
diff --git a/src/test/ui/return/tail-expr-as-potential-return.stderr b/src/test/ui/return/tail-expr-as-potential-return.stderr
index 87ef18878d6..dec1cbc4624 100644
--- a/src/test/ui/return/tail-expr-as-potential-return.stderr
+++ b/src/test/ui/return/tail-expr-as-potential-return.stderr
@@ -1,9 +1,10 @@
 error[E0308]: mismatched types
-  --> $DIR/tail-expr-as-potential-return.rs:7:9
+  --> $DIR/tail-expr-as-potential-return.rs:28:9
    |
 LL | /     if x {
 LL | |         Err(42)
    | |         ^^^^^^^ expected `()`, found enum `Result`
+LL | |                 //| HELP you might have meant to return this value
 LL | |     }
    | |_____- expected this to be `()`
    |
@@ -14,6 +15,23 @@ help: you might have meant to return this value
 LL |         return Err(42);
    |         ++++++        +
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/tail-expr-as-potential-return.rs:20:9
+   |
+LL | /     if x {
+LL | |         Err(42)
+   | |         ^^^^^^^ expected `()`, found enum `Result`
+LL | |                 //| HELP you might have meant to return this value
+LL | |     }
+   | |_____- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, {integer}>`
+help: you might have meant to return this value
+   |
+LL |         return Err(42);
+   |         ++++++        +
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.