about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-06-04 19:50:21 +0200
committerGitHub <noreply@github.com>2025-06-04 19:50:21 +0200
commit9ec41bcf72dd30d72cef2c3ea7bb8616e41585ce (patch)
treef0cdf39997b216bb2cc54e5e11f3d2cb7632c872
parent4151d15287d0e5e6c17965050624b885039ef915 (diff)
parentd5a9a005188322cd08dca018402e1593d3a5ebd5 (diff)
downloadrust-9ec41bcf72dd30d72cef2c3ea7bb8616e41585ce.tar.gz
rust-9ec41bcf72dd30d72cef2c3ea7bb8616e41585ce.zip
Rollup merge of #141932 - azhogin:azhogin/async-drop-inside-asyncgen-fix, r=oli-obk
Fix for async drop inside async gen fn

Return value (for yield) is corrected for async drop inside async gen function.
In CFG, when internal async drop future is polled and returned `Poll<()>::Pending`, then async gen resume function returns `Poll<(OptRet)>::Pending`.

Fixes rust-lang/rust#140530
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/drop.rs34
-rw-r--r--tests/ui/async-await/async-drop/assign-incompatible-types.rs (renamed from tests/crashes/140530.rs)5
2 files changed, 31 insertions, 8 deletions
diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs
index 6b266da5a69..625e53f9959 100644
--- a/compiler/rustc_mir_transform/src/coroutine/drop.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs
@@ -382,12 +382,34 @@ pub(super) fn expand_async_drops<'tcx>(
             dropline_call_bb = Some(drop_call_bb);
         }
 
-        // value needed only for return-yields or gen-coroutines, so just const here
-        let value = Operand::Constant(Box::new(ConstOperand {
-            span: body.span,
-            user_ty: None,
-            const_: Const::from_bool(tcx, false),
-        }));
+        let value =
+            if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _))
+            {
+                // For AsyncGen we need `yield Poll<OptRet>::Pending`
+                let full_yield_ty = body.yield_ty().unwrap();
+                let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() };
+                let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() };
+                let yield_ty = args.type_at(0);
+                Operand::Constant(Box::new(ConstOperand {
+                    span: source_info.span,
+                    const_: Const::Unevaluated(
+                        UnevaluatedConst::new(
+                            tcx.require_lang_item(LangItem::AsyncGenPending, None),
+                            tcx.mk_args(&[yield_ty.into()]),
+                        ),
+                        full_yield_ty,
+                    ),
+                    user_ty: None,
+                }))
+            } else {
+                // value needed only for return-yields or gen-coroutines, so just const here
+                Operand::Constant(Box::new(ConstOperand {
+                    span: body.span,
+                    user_ty: None,
+                    const_: Const::from_bool(tcx, false),
+                }))
+            };
+
         use rustc_middle::mir::AssertKind::ResumedAfterDrop;
         let panic_bb = insert_panic_block(tcx, body, ResumedAfterDrop(coroutine_kind));
 
diff --git a/tests/crashes/140530.rs b/tests/ui/async-await/async-drop/assign-incompatible-types.rs
index 7e0372a4bd8..359939ff9ac 100644
--- a/tests/crashes/140530.rs
+++ b/tests/ui/async-await/async-drop/assign-incompatible-types.rs
@@ -1,7 +1,8 @@
-//@ known-bug: #140530
+// ex-ice: #140530
 //@ edition: 2024
-
+//@ build-pass
 #![feature(async_drop, gen_blocks)]
+#![allow(incomplete_features)]
 async gen fn a() {
   _ = async {}
 }