Skip to content

Commit 94bb2d2

Browse files
authored
Rollup merge of #121664 - compiler-errors:adjust-error-yield-lowering, r=spastorino
Adjust error `yield`/`await` lowering Adjust the lowering of `yield`/`await` outside of their correct scopes so that we no longer make orpan HIR exprs. Previously, `yield EXPR` would be lowered directly to `hir::TyKind::Error` (which I'll call `<error>`) which means that `EXPR` was not present in the HIR, but now we lower it to `{ EXPR; <error> }` so that `EXPR` is not orphaned. Fixes #121096
2 parents 7265130 + e0a726c commit 94bb2d2

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+43-9
Original file line numberDiff line numberDiff line change
@@ -760,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
760760
Some(hir::CoroutineKind::Coroutine(_))
761761
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
762762
| None => {
763-
return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
764-
await_kw_span,
765-
item_span: self.current_item,
766-
}));
763+
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
764+
// is not accidentally orphaned.
765+
let stmt_id = self.next_id();
766+
let expr_err = self.expr(
767+
expr.span,
768+
hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
769+
await_kw_span,
770+
item_span: self.current_item,
771+
})),
772+
);
773+
return hir::ExprKind::Block(
774+
self.block_all(
775+
expr.span,
776+
arena_vec![self; hir::Stmt {
777+
hir_id: stmt_id,
778+
kind: hir::StmtKind::Semi(expr),
779+
span: expr.span,
780+
}],
781+
Some(self.arena.alloc(expr_err)),
782+
),
783+
None,
784+
);
767785
}
768786
};
769787

@@ -1496,12 +1514,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
14961514
}
14971515

14981516
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1517+
let yielded =
1518+
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
1519+
14991520
let is_async_gen = match self.coroutine_kind {
15001521
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
15011522
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
15021523
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
1503-
return hir::ExprKind::Err(
1504-
self.dcx().emit_err(AsyncCoroutinesNotSupported { span }),
1524+
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
1525+
// is not accidentally orphaned.
1526+
let stmt_id = self.next_id();
1527+
let expr_err = self.expr(
1528+
yielded.span,
1529+
hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),
1530+
);
1531+
return hir::ExprKind::Block(
1532+
self.block_all(
1533+
yielded.span,
1534+
arena_vec![self; hir::Stmt {
1535+
hir_id: stmt_id,
1536+
kind: hir::StmtKind::Semi(yielded),
1537+
span: yielded.span,
1538+
}],
1539+
Some(self.arena.alloc(expr_err)),
1540+
),
1541+
None,
15051542
);
15061543
}
15071544
Some(hir::CoroutineKind::Coroutine(_)) => {
@@ -1531,9 +1568,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
15311568
}
15321569
};
15331570

1534-
let yielded =
1535-
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
1536-
15371571
if is_async_gen {
15381572
// `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
15391573
// This ensures that we store our resumed `ResumeContext` correctly, and also that
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@ edition:2021
2+
3+
fn main() {
4+
async {
5+
use std::ops::Add;
6+
let _ = 1.add(3);
7+
}.await
8+
//~^ ERROR `await` is only allowed inside `async` functions and blocks
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0728]: `await` is only allowed inside `async` functions and blocks
2+
--> $DIR/async-outside-of-await-issue-121096.rs:7:7
3+
|
4+
LL | fn main() {
5+
| ---- this is not `async`
6+
...
7+
LL | }.await
8+
| ^^^^^ only allowed inside `async` functions and blocks
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0728`.

0 commit comments

Comments
 (0)