python / python/cpython

dis: FOR_ITER says it no longer pops the stack in 3.12 but it still does when the iterator ended normally

Open
#121,399 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

docs
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Documentation

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:

https://github.com/python/cpython/blob/cecd6012b0ed5dca3916ae341e705ae44172991d/Doc/library/dis.rst?plain=1#L1334-L1342

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:

https://github.com/python/cpython/blob/cecd6012b0ed5dca3916ae341e705ae44172991d/Python/generated_cases.c.h#L3069

https://github.com/python/cpython/blob/cecd6012b0ed5dca3916ae341e705ae44172991d/Python/generated_cases.c.h#L3085-L3087

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).

Is it worth documenting the 2 different cases?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the FOR_ITER wording in Doc/library/dis.rst and compare it with the FOR_ITER and END_FOR cases in Python/generated_cases.c.h cited by the issue. Verify the normal and alternate iterator-exhaustion paths in Python 3.12 and 3.13, then update the documentation if both stack behaviors are confirmed and can be explained clearly.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers, documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.