未验证 提交 e3a514c4 编写于 作者: D Dylan DPC 提交者: GitHub

Rollup merge of #71174 - Nokel81:fix-async-main-error, r=petrochenkov

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

This PR fixes #68523.
......@@ -431,6 +431,7 @@
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
......
`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<i32, ()> {
Ok(1)
}
```
......@@ -82,10 +82,9 @@ fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
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 @@ fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
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 {
......
......@@ -1318,10 +1318,7 @@ fn note_obligation_cause_for_async_await(
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") };
......
......@@ -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;
}
......
// edition:2018
#![feature(start)]
#[start]
pub async fn start(_: isize, _: *const *const u8) -> isize {
//~^ ERROR start is not allowed to be `async`
0
}
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`.
// edition:2018
async fn main() -> Result<i32, ()> {
//~^ ERROR `main` function is not allowed to be `async`
//~^^ ERROR `main` has invalid return type `impl std::future::Future`
Ok(1)
}
error[E0277]: `main` has invalid return type `impl std::future::Future`
--> $DIR/issue-68523.rs:3:20
|
LL | async fn main() -> Result<i32, ()> {
| ^^^^^^^^^^^^^^^ `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<i32, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册