ruff PLR1736: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
Fix captures list value at loop start; original uses rebound value, causing divergence when list is reassigned in outer scope during iteration.
Program
Output
Before: lst[0]=10, x=10 Before: lst[1]=88, x=20
Before: lst[0]=10, x=10 Before: lst[1]=20, x=20
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · high
The fix replaces `lst[i]` with the loop variable `x`, assuming the list is not mutated during iteration. However, the program rebinds `lst` to a new list `[99, 88]` when `i == 0`, so on the next iteration `lst[1]` reads from the new list (88) while `x` still yields the original element (20). This changes the program's observable output and is a silent wrong result in plausible code.
Explanation Nemotron 3 Super unverified
The original loop iterates over `enumerate(lst)`, where each iteration evaluates `lst` to get its current value; when `lst` is rebound inside the loop (to `[99, 88]`), subsequent iterations use that new list, so on the second iteration `lst[1]` yields `88`. The fix replaces `lst[i]` with `x`, which captures the element from the *original* enumeration snapshot taken at loop start (`[10, 20]`). Since `x` never changes per iteration, it always reflects the initial list’s values, ignoring the rebinding of `lst`. Thus the printed second element differs: `88` vs `20`. This change alters behavior because it decouples the index lookup from the dynamically updated list.
Reproduce
- file
prog.py(the before program)- minimized program
- r1-p002.py
- evidence sheet
- r1-p002.md
- regression fixture
- r1-p002.py the minimized program with a header stating the observed change, for the tool's test suite
python3 prog.py ruff check --preview --isolated --select PLR1736 --fix prog.py python3 prog.py
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
PLR1736 fix · PLR1736 f-string list indexing · enumerate loop variable substitution · list rebinding during iteration
- related astral-sh/ruff/issues/29422 umbrella issue listing PLR1736 among many rules but no specific rebinding construct
- related astral-sh/ruff/issues/25182 tracks additional false positives for PLR1736 but does not describe rebinding of the iterated list
- related astral-sh/ruff/issues/12594 PLR1736 defect but about custom start index, not list rebinding
- related astral-sh/ruff/issues/9010 autofix conflict between PLR1736 and FURB148, different cause than rebinding
- duplicate astral-sh/ruff/issues/8969 exact same PLR1736 unsafe fix that changes semantics when the iterated list is rebound in the loop
Details
- program
- Mutable local rebound in outer scope
- hazard
- Fix captures list value at loop start; original uses rebound value, causing divergence when list is reassigned in outer scope during iteration.
- oracle
stdout before: Before: lst[0]=10, x=10 Before: lst[1]=88, x=20 stdout after: Before: lst[0]=10, x=10 Before: lst[1]=20, x=20- run
- 2026-10-17T21-04-33-755Z-llwi-ruff-PLR1736
generated program (6 lines) and the fix's diff
--- orig.py 2026-10-17 17:04:47.037870536 -0400 +++ fixed.py 2026-10-17 17:04:47.205872429 -0400 @@ -1,6 +1,6 @@ lst = [10, 20] for i, x in enumerate(lst): - print(f'Before: lst[{i}]={lst[i]}, x={x}') + print(f'Before: lst[{i}]={x}, x={x}') if i == 0: lst = [99, 88] # Rebinding in outer scope print(f'After: lst[{i}]={lst[i]}, x={x}')
rule documentation given to the models
# unnecessary-list-index-lookup (PLR1736)
Derived from the **Pylint** linter.
Fix is always available.
## What it does
Checks for index-based list accesses during `enumerate` iterations.
## Why is this bad?
When iterating over a list with `enumerate`, the current item is already
available alongside its index. Using the index to look up the item is
unnecessary.
## Example
```python
letters = ["a", "b", "c"]
for index, letter in enumerate(letters):
print(letters[index])
```
Use instead:
```python
letters = ["a", "b", "c"]
for index, letter in enumerate(letters):
print(letter)
```