From 6120acec8799616dbd7e646c1d7957eab894202b Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 8 Apr 2020 15:39:02 -0400 Subject: [PATCH] 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 --- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0752.md | 11 ++++++++ .../error_reporting/on_unimplemented.rs | 14 ++++------ .../traits/error_reporting/suggestions.rs | 5 +--- src/librustc_typeck/lib.rs | 28 +++++++++++++++++-- src/test/ui/async-await/issue-68523-start.rs | 9 ++++++ .../ui/async-await/issue-68523-start.stderr | 9 ++++++ src/test/ui/async-await/issue-68523.rs | 7 +++++ src/test/ui/async-await/issue-68523.stderr | 18 ++++++++++++ 9 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0752.md create mode 100644 src/test/ui/async-await/issue-68523-start.rs create mode 100644 src/test/ui/async-await/issue-68523-start.stderr create mode 100644 src/test/ui/async-await/issue-68523.rs create mode 100644 src/test/ui/async-await/issue-68523.stderr diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 225ede851b4d9..bc04809eaa1df 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -431,6 +431,7 @@ E0748: include_str!("./error_codes/E0748.md"), E0749: include_str!("./error_codes/E0749.md"), E0750: include_str!("./error_codes/E0750.md"), E0751: include_str!("./error_codes/E0751.md"), +E0752: include_str!("./error_codes/E0752.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0752.md b/src/librustc_error_codes/error_codes/E0752.md new file mode 100644 index 0000000000000..86945f83b5524 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0752.md @@ -0,0 +1,11 @@ +`fn main()` or the specified start function is not allowed to be +async. You might be seeing this error because your async runtime +library is not set up correctly. + +Erroneous code example: + +```compile_fail,E0752 +async fn main() -> Result { + Ok(1) +} +``` diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs index 1ecc7fdafc442..3b6c741b89043 100644 --- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs @@ -82,10 +82,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { match &node { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => { self.describe_generator(*body_id).or_else(|| { - Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header { - "an async function" - } else { - "a function" + Some(match sig.header { + hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async function", + _ => "a function", }) }) } @@ -97,10 +96,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { kind: hir::ImplItemKind::Fn(sig, body_id), .. }) => self.describe_generator(*body_id).or_else(|| { - Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header { - "an async method" - } else { - "a method" + Some(match sig.header { + hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async method", + _ => "a method", }) }), hir::Node::Expr(hir::Expr { diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 254db6cb869b1..982ceec7dca21 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1313,10 +1313,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let is_async = inner_generator_body .and_then(|body| body.generator_kind()) - .map(|generator_kind| match generator_kind { - hir::GeneratorKind::Async(..) => true, - _ => false, - }) + .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..))) .unwrap_or(false); let (await_or_yield, an_await_or_yield) = if is_async { ("await", "an await") } else { ("yield", "a yield") }; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index df8290fd018c5..cd76184c9bf2d 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -159,7 +159,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { match main_t.kind { ty::FnDef(..) => { if let Some(Node::Item(it)) = tcx.hir().find(main_id) { - if let hir::ItemKind::Fn(.., ref generics, _) = it.kind { + if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { let mut error = false; if !generics.params.is_empty() { 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) { .emit(); error = true; } + if let hir::IsAsync::Async = sig.header.asyncness { + let span = tcx.sess.source_map().guess_head_span(it.span); + struct_span_err!( + tcx.sess, + span, + E0752, + "`main` function is not allowed to be `async`" + ) + .span_label(span, "`main` function is not allowed to be `async`") + .emit(); + error = true; + } if error { return; } @@ -226,7 +238,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { match start_t.kind { ty::FnDef(..) => { if let Some(Node::Item(it)) = tcx.hir().find(start_id) { - if let hir::ItemKind::Fn(.., ref generics, _) = it.kind { + if let hir::ItemKind::Fn(ref sig, ref generics, _) = it.kind { let mut error = false; if !generics.params.is_empty() { struct_span_err!( @@ -250,6 +262,18 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { .emit(); error = true; } + if let hir::IsAsync::Async = sig.header.asyncness { + let span = tcx.sess.source_map().guess_head_span(it.span); + struct_span_err!( + tcx.sess, + span, + E0752, + "start is not allowed to be `async`" + ) + .span_label(span, "start is not allowed to be `async`") + .emit(); + error = true; + } if error { return; } diff --git a/src/test/ui/async-await/issue-68523-start.rs b/src/test/ui/async-await/issue-68523-start.rs new file mode 100644 index 0000000000000..5988dffd68fa7 --- /dev/null +++ b/src/test/ui/async-await/issue-68523-start.rs @@ -0,0 +1,9 @@ +// edition:2018 + +#![feature(start)] + +#[start] +pub async fn start(_: isize, _: *const *const u8) -> isize { +//~^ ERROR start is not allowed to be `async` + 0 +} diff --git a/src/test/ui/async-await/issue-68523-start.stderr b/src/test/ui/async-await/issue-68523-start.stderr new file mode 100644 index 0000000000000..e471945900e7d --- /dev/null +++ b/src/test/ui/async-await/issue-68523-start.stderr @@ -0,0 +1,9 @@ +error[E0752]: start is not allowed to be `async` + --> $DIR/issue-68523-start.rs:6:1 + | +LL | pub async fn start(_: isize, _: *const *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ start is not allowed to be `async` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0752`. diff --git a/src/test/ui/async-await/issue-68523.rs b/src/test/ui/async-await/issue-68523.rs new file mode 100644 index 0000000000000..e6250c40c714c --- /dev/null +++ b/src/test/ui/async-await/issue-68523.rs @@ -0,0 +1,7 @@ +// edition:2018 + +async fn main() -> Result { +//~^ ERROR `main` function is not allowed to be `async` +//~^^ ERROR `main` has invalid return type `impl std::future::Future` + Ok(1) +} diff --git a/src/test/ui/async-await/issue-68523.stderr b/src/test/ui/async-await/issue-68523.stderr new file mode 100644 index 0000000000000..62e37cf2629d7 --- /dev/null +++ b/src/test/ui/async-await/issue-68523.stderr @@ -0,0 +1,18 @@ +error[E0277]: `main` has invalid return type `impl std::future::Future` + --> $DIR/issue-68523.rs:3:20 + | +LL | async fn main() -> Result { + | ^^^^^^^^^^^^^^^ `main` can only return types that implement `std::process::Termination` + | + = help: consider using `()`, or a `Result` + +error[E0752]: `main` function is not allowed to be `async` + --> $DIR/issue-68523.rs:3:1 + | +LL | async fn main() -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0752. +For more information about an error, try `rustc --explain E0277`.