Skip to content

Commit 4ab3f0f

Browse files
committed
[mypyc] Free generator after await encounters StopIteration
Previously the awaited generator could stay alive until the generator that performed the await was freed, delaying object reclamation. The refcount analysis doesn't understand registers spilled to the environment, so we need to manually clear the value. Consider code like this: ``` async def foo() -> None: await bar() await zar() ``` Previously, the `bar()` generator was only freed at end of `foo()`. Now we release it before `await zar()`, as expected.
1 parent 71942c0 commit 4ab3f0f

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

mypyc/irbuild/statement.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,10 @@ def emit_yield_from_or_await(
940940
# If it wasn't, this reraises the exception.
941941
builder.activate_block(stop_block)
942942
builder.assign(result, builder.call_c(check_stop_op, [], line), line)
943+
# Clear the spilled iterator/coroutine so that it will be freed.
944+
# Otherwise, the freeing of the spilled register would likely be delayed.
945+
err = builder.add(LoadErrorValue(object_rprimitive))
946+
builder.assign(iter_reg, err, line)
943947
builder.goto(done_block)
944948

945949
builder.activate_block(main_block)

0 commit comments

Comments
 (0)