Skip to content

Commit 6120ace

Browse files
author
Sebastian Malton
committed
Check that main/start is not async
* Add new error code E0752 * Add span to hir::IsAsync::Yes * Emit an error if main or the start function is marked as async * Add two regression tests Fix formatting errors and bless test outputs * move tests to ui/async-await fix test error text remove span from IsAsync
1 parent 8d67f57 commit 6120ace

File tree

9 files changed

+88
-14
lines changed

9 files changed

+88
-14
lines changed

src/librustc_error_codes/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ E0748: include_str!("./error_codes/E0748.md"),
431431
E0749: include_str!("./error_codes/E0749.md"),
432432
E0750: include_str!("./error_codes/E0750.md"),
433433
E0751: include_str!("./error_codes/E0751.md"),
434+
E0752: include_str!("./error_codes/E0752.md"),
434435
;
435436
// E0006, // merged with E0005
436437
// E0008, // cannot bind by-move into a pattern guard
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
`fn main()` or the specified start function is not allowed to be
2+
async. You might be seeing this error because your async runtime
3+
library is not set up correctly.
4+
5+
Erroneous code example:
6+
7+
```compile_fail,E0752
8+
async fn main() -> Result<i32, ()> {
9+
Ok(1)
10+
}
11+
```

src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
8282
match &node {
8383
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
8484
self.describe_generator(*body_id).or_else(|| {
85-
Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
86-
"an async function"
87-
} else {
88-
"a function"
85+
Some(match sig.header {
86+
hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async function",
87+
_ => "a function",
8988
})
9089
})
9190
}
@@ -97,10 +96,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
9796
kind: hir::ImplItemKind::Fn(sig, body_id),
9897
..
9998
}) => self.describe_generator(*body_id).or_else(|| {
100-
Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
101-
"an async method"
102-
} else {
103-
"a method"
99+
Some(match sig.header {
100+
hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async method",
101+
_ => "a method",
104102
})
105103
}),
106104
hir::Node::Expr(hir::Expr {

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1313,10 +1313,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
13131313

13141314
let is_async = inner_generator_body
13151315
.and_then(|body| body.generator_kind())
1316-
.map(|generator_kind| match generator_kind {
1317-
hir::GeneratorKind::Async(..) => true,
1318-
_ => false,
1319-
})
1316+
.map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
13201317
.unwrap_or(false);
13211318
let (await_or_yield, an_await_or_yield) =
13221319
if is_async { ("await", "an await") } else { ("yield", "a yield") };

src/librustc_typeck/lib.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
159159
match main_t.kind {
160160
ty::FnDef(..) => {
161161
if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
162-
if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
162+
if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
163163
let mut error = false;
164164
if !generics.params.is_empty() {
165165
let msg = "`main` function is not allowed to have generic \
@@ -182,6 +182,18 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
182182
.emit();
183183
error = true;
184184
}
185+
if let hir::IsAsync::Async = sig.header.asyncness {
186+
let span = tcx.sess.source_map().guess_head_span(it.span);
187+
struct_span_err!(
188+
tcx.sess,
189+
span,
190+
E0752,
191+
"`main` function is not allowed to be `async`"
192+
)
193+
.span_label(span, "`main` function is not allowed to be `async`")
194+
.emit();
195+
error = true;
196+
}
185197
if error {
186198
return;
187199
}
@@ -226,7 +238,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
226238
match start_t.kind {
227239
ty::FnDef(..) => {
228240
if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
229-
if let hir::ItemKind::Fn(.., ref generics, _) = it.kind {
241+
if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind {
230242
let mut error = false;
231243
if !generics.params.is_empty() {
232244
struct_span_err!(
@@ -250,6 +262,18 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
250262
.emit();
251263
error = true;
252264
}
265+
if let hir::IsAsync::Async = sig.header.asyncness {
266+
let span = tcx.sess.source_map().guess_head_span(it.span);
267+
struct_span_err!(
268+
tcx.sess,
269+
span,
270+
E0752,
271+
"start is not allowed to be `async`"
272+
)
273+
.span_label(span, "start is not allowed to be `async`")
274+
.emit();
275+
error = true;
276+
}
253277
if error {
254278
return;
255279
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// edition:2018
2+
3+
#![feature(start)]
4+
5+
#[start]
6+
pub async fn start(_: isize, _: *const *const u8) -> isize {
7+
//~^ ERROR start is not allowed to be `async`
8+
0
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0752]: start is not allowed to be `async`
2+
--> $DIR/issue-68523-start.rs:6:1
3+
|
4+
LL | pub async fn start(_: isize, _: *const *const u8) -> isize {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ start is not allowed to be `async`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0752`.
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// edition:2018
2+
3+
async fn main() -> Result<i32, ()> {
4+
//~^ ERROR `main` function is not allowed to be `async`
5+
//~^^ ERROR `main` has invalid return type `impl std::future::Future`
6+
Ok(1)
7+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: `main` has invalid return type `impl std::future::Future`
2+
--> $DIR/issue-68523.rs:3:20
3+
|
4+
LL | async fn main() -> Result<i32, ()> {
5+
| ^^^^^^^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
6+
|
7+
= help: consider using `()`, or a `Result`
8+
9+
error[E0752]: `main` function is not allowed to be `async`
10+
--> $DIR/issue-68523.rs:3:1
11+
|
12+
LL | async fn main() -> Result<i32, ()> {
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`
14+
15+
error: aborting due to 2 previous errors
16+
17+
Some errors have detailed explanations: E0277, E0752.
18+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)