-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
Closed
Labels
type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
Reproducer:
def foo():
a = [1, 2, 3]
exhit = iter(a)
for _ in exhit:
pass
a.append("this should'be in exhit")
print(f"got {list(exhit)}, should be []")
foo()
foo()
foo()
foo()
foo()
foo()
Output:
got [], should be []
got [], should be []
got [], should be []
got [], should be []
got [], should be []
got ["this should'be in exhit"], should be []
Obviously, the last line is incorrect.
Output with a PYTHON_LLTRACE=2
env:
got [], should be []
got [], should be []
got [], should be []
got [], should be []
got [], should be []
Optimizing foo (/home/eclips4/programming-languages/cpython/example.py:1) at byte offset 42
1 ADD_TO_TRACE: _START_EXECUTOR (0, target=21, operand=0x7f4646e59832)
21: JUMP_BACKWARD(5)
2 ADD_TO_TRACE: _CHECK_VALIDITY_AND_SET_IP (0, target=21, operand=0x7f4646e59832)
3 ADD_TO_TRACE: _TIER2_RESUME_CHECK (0, target=21, operand=0)
18: FOR_ITER_LIST(3)
4 ADD_TO_TRACE: _CHECK_VALIDITY_AND_SET_IP (0, target=18, operand=0x7f4646e5982c)
5 ADD_TO_TRACE: _ITER_CHECK_LIST (3, target=18, operand=0)
6 ADD_TO_TRACE: _GUARD_NOT_EXHAUSTED_LIST (3, target=18, operand=0)
7 ADD_TO_TRACE: _ITER_NEXT_LIST (3, target=18, operand=0)
20: STORE_FAST(2)
8 ADD_TO_TRACE: _CHECK_VALIDITY_AND_SET_IP (0, target=20, operand=0x7f4646e59830)
9 ADD_TO_TRACE: _STORE_FAST (2, target=20, operand=0)
21: JUMP_BACKWARD(5)
10 ADD_TO_TRACE: _CHECK_VALIDITY_AND_SET_IP (0, target=21, operand=0x7f4646e59832)
11 ADD_TO_TRACE: _JUMP_TO_TOP (0, target=0, operand=0)
Created a proto-trace for foo (/home/eclips4/programming-languages/cpython/example.py:1) at byte offset 36 -- length 11
Optimized trace (length 10):
0 OPTIMIZED: _START_EXECUTOR (0, jump_target=7, operand=0x7f4646e59e80)
1 OPTIMIZED: _TIER2_RESUME_CHECK (0, jump_target=7, operand=0)
2 OPTIMIZED: _ITER_CHECK_LIST (3, jump_target=8, operand=0)
3 OPTIMIZED: _GUARD_NOT_EXHAUSTED_LIST (3, jump_target=9, operand=0)
4 OPTIMIZED: _ITER_NEXT_LIST (3, target=18, operand=0)
5 OPTIMIZED: _STORE_FAST_2 (2, target=20, operand=0)
6 OPTIMIZED: _JUMP_TO_TOP (0, target=0, operand=0)
7 OPTIMIZED: _DEOPT (0, target=21, operand=0)
8 OPTIMIZED: _EXIT_TRACE (0, exit_index=0, operand=0)
9 OPTIMIZED: _EXIT_TRACE (0, exit_index=1, operand=0)
got ["this should'be in exhit"], should be []
It's definitely related to this part of code:
Lines 1027 to 1033 in e4a97a7
if (is_for_iter_test[opcode]) { | |
/* Target the POP_TOP immediately after the END_FOR, | |
* leaving only the iterator on the stack. */ | |
int extended_arg = inst->oparg > 255; | |
int32_t next_inst = target + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + extended_arg; | |
jump_target = next_inst + inst->oparg + 1; | |
} |
I guess the culprit is there. If we remove the _GUARD_NOT_EXHAUSTED_LIST
from is_for_iter_test
, the problem will go away (although it can still be reproduced in other ways using other (range, tuple) iterators).
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux, macOS
Linked PRs
nerodono, lubaskinc0de, Kirill-Stepankov and KOT4N
Metadata
Metadata
Assignees
Labels
type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error