Skip to content

Commit ae3a2eb

Browse files
morealclaude
andcommitted
Handle CO_ITERABLE_COROUTINE flag in anext_awaitable
Generators decorated with @types.coroutine have the CO_ITERABLE_COROUTINE flag and can be used in await expressions. The PyAnextAwaitable's get_awaitable_iter method was missing this check, causing builtin anext() to fail with "object generator can't be used in 'await' expression" when used with such generators. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent be354cd commit ae3a2eb

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

crates/vm/src/builtins/asyncgenerator.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{PyCode, PyGenericAlias, PyStrRef, PyType, PyTypeRef};
1+
use super::{PyCode, PyGenerator, PyGenericAlias, PyStrRef, PyType, PyTypeRef};
22
use crate::{
33
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
44
builtins::PyBaseExceptionRef,
@@ -592,6 +592,24 @@ impl PyAnextAwaitable {
592592
let awaitable = if wrapped.class().is(vm.ctx.types.coroutine_type) {
593593
// Coroutine - get __await__ later
594594
wrapped.clone()
595+
} else if let Some(generator) = wrapped.downcast_ref::<PyGenerator>() {
596+
// Generator with CO_ITERABLE_COROUTINE flag can be awaited
597+
// (e.g., generators decorated with @types.coroutine)
598+
if generator
599+
.as_coro()
600+
.frame()
601+
.code
602+
.flags
603+
.contains(crate::bytecode::CodeFlags::ITERABLE_COROUTINE)
604+
{
605+
// Return the generator itself as the iterator
606+
return Ok(wrapped.clone());
607+
} else {
608+
return Err(vm.new_type_error(format!(
609+
"object {} can't be used in 'await' expression",
610+
wrapped.class().name()
611+
)));
612+
}
595613
} else {
596614
// Try to get __await__ method
597615
if let Some(await_method) = vm.get_method(wrapped.clone(), identifier!(vm, __await__)) {

0 commit comments

Comments
 (0)