Skip to content

Commit 6b05b80

Browse files
committed
Suggest return type for async function without return type
1 parent 50d3ba5 commit 6b05b80

File tree

4 files changed

+102
-1
lines changed

4 files changed

+102
-1
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+16
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
921921
kind: hir::ImplItemKind::Fn(ref sig, ..),
922922
..
923923
}) => Some((&sig.decl, ident, false)),
924+
Node::Expr(&hir::Expr {
925+
hir_id,
926+
kind: hir::ExprKind::Closure(..),
927+
..
928+
}) if let Some(Node::Expr(&hir::Expr {
929+
hir_id,
930+
kind: hir::ExprKind::Call(..),
931+
..
932+
})) = self.tcx.hir().find_parent(hir_id) &&
933+
let Some(Node::Item(&hir::Item {
934+
ident,
935+
kind: hir::ItemKind::Fn(ref sig, ..),
936+
..
937+
})) = self.tcx.hir().find_parent(hir_id) => {
938+
Some((&sig.decl, ident, ident.name != sym::main))
939+
},
924940
_ => None,
925941
}
926942
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -704,10 +704,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
704704
}
705705
}
706706
hir::FnRetTy::Return(ty) => {
707+
let span = ty.span;
708+
709+
if let hir::TyKind::OpaqueDef(item_id, ..) = ty.kind
710+
&& let hir::Node::Item(hir::Item {
711+
kind: hir::ItemKind::OpaqueTy(op_ty),
712+
..
713+
}) = self.tcx.hir().get(item_id.hir_id())
714+
&& let hir::OpaqueTy {
715+
bounds: [bound], ..
716+
} = op_ty
717+
&& let hir::GenericBound::LangItemTrait(
718+
hir::LangItem::Future, _, _, generic_args) = bound
719+
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
720+
&& let hir::TypeBinding { kind, .. } = ty_binding
721+
&& let hir::TypeBindingKind::Equality { term } = kind
722+
&& let hir::Term::Ty(term_ty) = term {
723+
// Check if async function's return type was omitted.
724+
// Don't emit suggestions if the found type is `impl Future<...>`.
725+
debug!("suggest_missing_return_type: found = {:?}", found);
726+
if found.is_suggestable(self.tcx, false) {
727+
if term_ty.span.is_empty() {
728+
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
729+
return true;
730+
} else {
731+
err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
732+
}
733+
}
734+
}
735+
707736
// Only point to return type if the expected type is the return type, as if they
708737
// are not, the expectation must have been caused by something else.
709738
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
710-
let span = ty.span;
711739
let ty = self.astconv().ast_ty_to_ty(ty);
712740
debug!("suggest_missing_return_type: return type {:?}", ty);
713741
debug!("suggest_missing_return_type: expected type {:?}", ty);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// edition:2018
2+
3+
async fn hello() { //~ HELP try adding a return type
4+
0
5+
//~^ ERROR [E0308]
6+
}
7+
8+
async fn world() -> () {
9+
0
10+
//~^ ERROR [E0308]
11+
}
12+
13+
async fn suggest_await_in_async_fn_return() {
14+
hello()
15+
//~^ ERROR mismatched types [E0308]
16+
//~| HELP consider `await`ing on the `Future`
17+
//~| HELP consider using a semicolon here
18+
//~| SUGGESTION .await
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
3+
|
4+
LL | async fn hello() {
5+
| - help: try adding a return type: `-> i32`
6+
LL | 0
7+
| ^ expected `()`, found integer
8+
9+
error[E0308]: mismatched types
10+
--> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
11+
|
12+
LL | async fn world() -> () {
13+
| -- expected `()` because of return type
14+
LL | 0
15+
| ^ expected `()`, found integer
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
19+
|
20+
LL | hello()
21+
| ^^^^^^^ expected `()`, found opaque type
22+
|
23+
= note: expected unit type `()`
24+
found opaque type `impl Future<Output = ()>`
25+
help: consider `await`ing on the `Future`
26+
|
27+
LL | hello().await
28+
| ++++++
29+
help: consider using a semicolon here
30+
|
31+
LL | hello();
32+
| +
33+
34+
error: aborting due to 3 previous errors
35+
36+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)