summary refs log tree commit diff
path: root/compiler/rustc_ast_lowering/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-03-05 06:40:30 +0100
committerGitHub <noreply@github.com>2024-03-05 06:40:30 +0100
commit94bb2d2a974ece985dfea0da0622d4f987505dd3 (patch)
tree74bf2532698d90d3089cbca56caf93184690cc45 /compiler/rustc_ast_lowering/src
parent72651306b3e6d7308bb35897501940cd9b97baff (diff)
parente0a726ca4bc08d1009803a6c819f701173810761 (diff)
downloadrust-94bb2d2a974ece985dfea0da0622d4f987505dd3.tar.gz
rust-94bb2d2a974ece985dfea0da0622d4f987505dd3.zip
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
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs52
1 files changed, 43 insertions, 9 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 0b1cb124080..85b599902b9 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -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,
+                );
             }
         };
 
@@ -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(_)) => {
@@ -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