◐ Shell
clean mode source ↗

instruction improvements by youknowone · Pull Request #6829 · RustPython/RustPython

🧩 Analysis chain

🌐 Web query:

CPython 3.14 FOR_ITER stack_effect jump parameter dis module

💡 Result:

Short answer: dis.stack_effect(opcode.FOR_ITER, oparg, jump=...) — jump=True = jump taken (iterator exhausted) → stack effect 0; jump=False = fall-through (next value produced) → stack effect +1; jump=None (default) → returns the maximal effect (+1). See the dis docs. [1][2]

Sources:

  • dis.stack_effect documentation. [1]
  • FOR_ITER opcode description (notes on popping behavior and changes across versions). [2]

🌐 Web query:

CPython 3.14 FOR_ITER opcode behavior stack semantics

💡 Result:

Short answer — semantics in CPython 3.14:

  • Input stack before FOR_ITER: [..., iter] (iterator object at TOS).
  • Execution:
    • If next(iter) yields a value: FOR_ITER pushes that value, leaving the iterator beneath it. Resulting stack: [..., iter, value].
    • If iterator is exhausted (StopIteration): FOR_ITER removes the iterator from the stack (pop) and jumps forward by the instruction’s oparg (no value pushed).
  • So the two possible “after” states are [..., iter, value] (loop body runs) or [...] (loop exit — iterator removed and jump). This is the traditional FOR_ITER behaviour used by for-loops and comprehensions; 3.14 continues that semantics (with related bytecode/iterator machinery changes such as adding POP_ITER/virtual iterators). (stackoverflow.com)

If you want the exact C implementation lines in ceval.c for 3.14 I can fetch and cite them.

Citations:


🏁 Script executed:

cd crates/compiler-core && find . -type f -name "*.rs" | head -20

Repository: RustPython/RustPython

Length of output: 212


🏁 Script executed:

grep -r "FOR_ITER\|ForIter" crates/compiler-core/src/bytecode/ -n | head -30

Repository: RustPython/RustPython

Length of output: 1596


🏁 Script executed:

cat -n crates/compiler-core/src/bytecode/instruction.rs | sed -n '509,514p'

Repository: RustPython/RustPython

Length of output: 456


🏁 Script executed:

cat -n crates/compiler-core/src/bytecode/instruction.rs | sed -n '440,520p'

Repository: RustPython/RustPython

Length of output: 4188


🏁 Script executed:

grep -r "stack_effect" crates/compiler-core/src/ -n | grep -v "test" | head -20

Repository: RustPython/RustPython

Length of output: 784


🏁 Script executed:

grep -r "END_FOR\|POP_ITER" crates/compiler-core/src/bytecode/instruction.rs -n

Repository: RustPython/RustPython

Length of output: 336


🏁 Script executed:

cat -n crates/compiler-core/src/bytecode/instruction.rs | sed -n '575,610p'

Repository: RustPython/RustPython

Length of output: 2078


🏁 Script executed:

grep -rn "\.stack_effect\|stack_effect(" crates/compiler-core/src/ --include="*.rs" | grep -v "fn stack_effect" | head -30

Repository: RustPython/RustPython

Length of output: 188


🏁 Script executed:

grep -rn "stack_effect" crates/compiler/ --include="*.rs" | grep -v "test\|compiler-core" | head -20

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

grep -rn "stack_effect" crates/ --include="*.rs" | grep -v "fn stack_effect\|test\|//.*stack_effect" | head -40

Repository: RustPython/RustPython

Length of output: 565


🏁 Script executed:

cat -n crates/compiler-core/src/bytecode/instruction.rs | sed -n '1165,1175p'

Repository: RustPython/RustPython

Length of output: 581


🏁 Script executed:

git log --oneline -20 -- crates/compiler-core/src/bytecode/instruction.rs

Repository: RustPython/RustPython

Length of output: 120


🏁 Script executed:

cat -n crates/codegen/src/ir.rs | sed -n '475,510p'

Repository: RustPython/RustPython

Length of output: 1912


🏁 Script executed:

cat -n crates/stdlib/src/opcode.rs | sed -n '185,200p'

Repository: RustPython/RustPython

Length of output: 591


🏁 Script executed:

cat -n crates/codegen/src/ir.rs | sed -n '500,515p'

Repository: RustPython/RustPython

Length of output: 901


🏁 Script executed:

grep -A 20 "Self::ForIter" crates/codegen/src/ir.rs | head -30

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

cd crates/compiler-core && cat -n src/bytecode/instruction.rs | sed -n '602,603p'

Repository: RustPython/RustPython

Length of output: 191


🏁 Script executed:

cat -n crates/compiler-core/src/bytecode/instruction.rs | sed -n '602,602p'

Repository: RustPython/RustPython

Length of output: 146


Respect the jump parameter in ForIter stack_effect to match CPython 3.14 semantics.

The jump parameter is actively used by codegen (lines 480 and 505 in crates/codegen/src/ir.rs) to calculate correct stack depths for fall-through vs. jump paths, but the ForIter implementation ignores it and unconditionally returns +1. This causes incorrect stack depth analysis for the jump case.

When the jump is taken, the iterator is popped and execution jumps away; there is no net stack change. The implementation should return 0 when jump=True and 1 when jump=False.