Adjust error yield/await lowering

This commit is contained in:
Michael Goulet 2024-02-27 03:14:55 +00:00
parent fc3800f657
commit e0a726ca4b
3 changed files with 64 additions and 9 deletions

View File

@ -764,10 +764,28 @@ fn make_lowered_await(
Some(hir::CoroutineKind::Coroutine(_))
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
| None => {
return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
await_kw_span,
item_span: self.current_item,
}));
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
// is not accidentally orphaned.
let stmt_id = self.next_id();
let expr_err = self.expr(
expr.span,
hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
await_kw_span,
item_span: self.current_item,
})),
);
return hir::ExprKind::Block(
self.block_all(
expr.span,
arena_vec![self; hir::Stmt {
hir_id: stmt_id,
kind: hir::StmtKind::Semi(expr),
span: expr.span,
}],
Some(self.arena.alloc(expr_err)),
),
None,
);
}
};
@ -1500,12 +1518,31 @@ fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
}
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
let yielded =
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
let is_async_gen = match self.coroutine_kind {
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
return hir::ExprKind::Err(
self.dcx().emit_err(AsyncCoroutinesNotSupported { span }),
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
// is not accidentally orphaned.
let stmt_id = self.next_id();
let expr_err = self.expr(
yielded.span,
hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),
);
return hir::ExprKind::Block(
self.block_all(
yielded.span,
arena_vec![self; hir::Stmt {
hir_id: stmt_id,
kind: hir::StmtKind::Semi(yielded),
span: yielded.span,
}],
Some(self.arena.alloc(expr_err)),
),
None,
);
}
Some(hir::CoroutineKind::Coroutine(_)) => {
@ -1535,9 +1572,6 @@ fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::Expr
}
};
let yielded =
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
if is_async_gen {
// `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
// This ensures that we store our resumed `ResumeContext` correctly, and also that

View File

@ -0,0 +1,9 @@
//@ edition:2021
fn main() {
async {
use std::ops::Add;
let _ = 1.add(3);
}.await
//~^ ERROR `await` is only allowed inside `async` functions and blocks
}

View File

@ -0,0 +1,12 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/async-outside-of-await-issue-121096.rs:7:7
|
LL | fn main() {
| ---- this is not `async`
...
LL | }.await
| ^^^^^ only allowed inside `async` functions and blocks
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0728`.