You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
dis: FOR_ITER says it no longer pops the stack in 3.12 but it still does when the iterator ended normally #121399
The FOR_ITER docs in the dis module say "Up until 3.11 the iterator was popped when it was exhausted". This sounds like in 3.12+ the iterator is not popped anymore:
``STACK[-1]`` is an :term:`iterator`. Call its :meth:`~iterator.__next__` method.
If this yields a new value, push it on the stack (leaving the iterator below
it). If the iterator indicates it is exhausted then the byte code counter is
incremented by *delta*.
.. versionchanged:: 3.12
Up until 3.11 the iterator was popped when it was exhausted.
Instead there is a new opcode END_FOR, which takes care of popping the iterator off the stack. This surprised me because in 3.12 END_FOR is supposed to remove 2 elements from the top of the stack. But if the iterator ends normally, there will only be the iterator at the top. I tried to document my thought process in this godbolt repro.
Reading the generated code for FOR_ITER, specifically:
/* Jump forward oparg, then skip following END_FOR and POP_TOP instruction */
JUMPBY(oparg+2);
it looks like there are 2 cases:
If the iterator ends normally, FOR_ITER pops the iterator off the stack, then it skips the next END_FOR (and in 3.13 POP_TOP) instructions.
Otherwise (I'm not sure when that happens?), the iterator ends with both the iter and iter() on the stack, which are both popped by END_FOR (and in 3.13 POP_TOP).
Activity
Undo FOR_ITER/END_FOR fix for 3.12
Undo FOR_ITER/END_FOR fix for 3.12
Undo FOR_ITER/END_FOR fix for 3.12