Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add CO_ITERABLE_COROUTINE flag and fix types tests
- Add ITERABLE_COROUTINE (0x0100) to CodeFlags in bytecode.rs
- Update frame.rs to check for both COROUTINE and ITERABLE_COROUTINE flags
  when validating 'yield from' on coroutine objects
- Remove False and workaround in types.coroutine() now that the flag is supported
- Remove @unittest.expectedFailure from test_async_def and test_genfunc

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  • Loading branch information
moreal and claude committed Jan 22, 2026
commit 6b98862820b46e82ca49a13df172d4fb39a5e425
2 changes: 0 additions & 2 deletions Lib/test/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,6 @@ def _test_gen():

class TestOneTrickPonyABCs(ABCTestCase):

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_Awaitable(self):
def gen():
yield
Expand Down Expand Up @@ -840,7 +839,6 @@ class CoroLike: pass
CoroLike = None
support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_Coroutine(self):
def gen():
yield
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2174,7 +2174,6 @@ def foo():
foo = types.coroutine(foo)
self.assertIs(aw, foo())

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_async_def(self):
# Test that types.coroutine passes 'async def' coroutines
# without modification
Expand Down Expand Up @@ -2431,7 +2430,6 @@ def foo():
foo = types.coroutine(foo)
self.assertIs(foo(), gencoro)

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_genfunc(self):
def gen(): yield
self.assertIs(types.coroutine(gen), gen)
Expand Down
3 changes: 1 addition & 2 deletions Lib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ def coroutine(func):
if not callable(func):
raise TypeError('types.coroutine() expects a callable')

# XXX RUSTPYTHON TODO: iterable coroutine
if (False and func.__class__ is FunctionType and
if (func.__class__ is FunctionType and
getattr(func, '__code__', None).__class__ is CodeType):

co_flags = func.__code__.co_flags
Expand Down
1 change: 1 addition & 0 deletions crates/compiler-core/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ bitflags! {
const VARKEYWORDS = 0x0008;
const GENERATOR = 0x0020;
const COROUTINE = 0x0080;
const ITERABLE_COROUTINE = 0x0100;
/// If a code object represents a function and has a docstring,
/// this bit is set and the first item in co_consts is the docstring.
const HAS_DOCSTRING = 0x4000000;
Expand Down
4 changes: 3 additions & 1 deletion crates/vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,9 @@ impl ExecutingFrame<'_> {
let iterable = self.pop_value();
let iter = if iterable.class().is(vm.ctx.types.coroutine_type) {
// Coroutine requires CO_COROUTINE or CO_ITERABLE_COROUTINE flag
if !self.code.flags.intersects(bytecode::CodeFlags::COROUTINE) {
if !self.code.flags.intersects(
bytecode::CodeFlags::COROUTINE | bytecode::CodeFlags::ITERABLE_COROUTINE,
) {
return Err(vm.new_type_error(
"cannot 'yield from' a coroutine object in a non-coroutine generator"
.to_owned(),
Expand Down