Skip to content
/ rust Public
forked from rust-lang/rust

Commit

Permalink
Rollup merge of rust-lang#121664 - compiler-errors:adjust-error-yield…
Browse files Browse the repository at this point in the history
…-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 rust-lang#121096
  • Loading branch information
jhpratt authored Mar 5, 2024
2 parents f5d4a5d + e0a726c commit b4245e1
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
52 changes: 43 additions & 9 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
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,
);
}
};

Expand Down Expand Up @@ -1496,12 +1514,31 @@ impl<'hir> LoweringContext<'_, '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(_)) => {
Expand Down Expand Up @@ -1531,9 +1568,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};

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
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/async-await/async-outside-of-await-issue-121096.rs
Original file line number Diff line number Diff line change
@@ -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
}
12 changes: 12 additions & 0 deletions tests/ui/async-await/async-outside-of-await-issue-121096.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit b4245e1

Please sign in to comment.