Skip to content

Commit

Permalink
Suggest return type for async function without return type
Browse files Browse the repository at this point in the history
  • Loading branch information
jieyouxu committed Feb 6, 2023
1 parent 50d3ba5 commit 6b05b80
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 1 deletion.
16 changes: 16 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(ref sig, ..),
..
}) => Some((&sig.decl, ident, false)),
Node::Expr(&hir::Expr {
hir_id,
kind: hir::ExprKind::Closure(..),
..
}) if let Some(Node::Expr(&hir::Expr {
hir_id,
kind: hir::ExprKind::Call(..),
..
})) = self.tcx.hir().find_parent(hir_id) &&
let Some(Node::Item(&hir::Item {
ident,
kind: hir::ItemKind::Fn(ref sig, ..),
..
})) = self.tcx.hir().find_parent(hir_id) => {
Some((&sig.decl, ident, ident.name != sym::main))
},
_ => None,
}
}
Expand Down
30 changes: 29 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,10 +704,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
hir::FnRetTy::Return(ty) => {
let span = ty.span;

if let hir::TyKind::OpaqueDef(item_id, ..) = ty.kind
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty),
..
}) = self.tcx.hir().get(item_id.hir_id())
&& let hir::OpaqueTy {
bounds: [bound], ..
} = op_ty
&& let hir::GenericBound::LangItemTrait(
hir::LangItem::Future, _, _, generic_args) = bound
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
&& let hir::TypeBinding { kind, .. } = ty_binding
&& let hir::TypeBindingKind::Equality { term } = kind
&& let hir::Term::Ty(term_ty) = term {
// Check if async function's return type was omitted.
// Don't emit suggestions if the found type is `impl Future<...>`.
debug!("suggest_missing_return_type: found = {:?}", found);
if found.is_suggestable(self.tcx, false) {
if term_ty.span.is_empty() {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
return true;
} else {
err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
}
}
}

// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
let span = ty.span;
let ty = self.astconv().ast_ty_to_ty(ty);
debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty);
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// edition:2018

async fn hello() { //~ HELP try adding a return type
0
//~^ ERROR [E0308]
}

async fn world() -> () {
0
//~^ ERROR [E0308]
}

async fn suggest_await_in_async_fn_return() {
hello()
//~^ ERROR mismatched types [E0308]
//~| HELP consider `await`ing on the `Future`
//~| HELP consider using a semicolon here
//~| SUGGESTION .await
}

fn main() {}
36 changes: 36 additions & 0 deletions tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
error[E0308]: mismatched types
--> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
|
LL | async fn hello() {
| - help: try adding a return type: `-> i32`
LL | 0
| ^ expected `()`, found integer

error[E0308]: mismatched types
--> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
|
LL | async fn world() -> () {
| -- expected `()` because of return type
LL | 0
| ^ expected `()`, found integer

error[E0308]: mismatched types
--> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
|
LL | hello()
| ^^^^^^^ expected `()`, found opaque type
|
= note: expected unit type `()`
found opaque type `impl Future<Output = ()>`
help: consider `await`ing on the `Future`
|
LL | hello().await
| ++++++
help: consider using a semicolon here
|
LL | hello();
| +

error: aborting due to 3 previous errors

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

0 comments on commit 6b05b80

Please sign in to comment.