ruff PLR1736: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
If the loop variable is named identically to the list (e.g., `for lst, lst in enumerate(lst): lst[lst]`), the fix risks incorrect variable capture due to name shadowing.
Program
Output
TypeError: string indices must be integers, not 'str' TypeError: string indices must be integers, not 'str' TypeError: string indices must be integers, not 'str'
(no stdout)
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory real · high
The rule assumes the enumerate target is a list and the loop variables are distinct (index, item), so it replaces lst[lst] with lst. In the program the same name lst is used for both variables; the inner lst binds to the element (a string), making the original indexing a TypeError that is caught and printed. After the fix the indexing is removed, the exception disappears, and the program prints nothing — a silent change in observable behavior.
Explanation Nemotron 3 Super unverified
The rewrite replaces `result = lst[lst]` with `result = lst`, changing the operation from indexing the list using its current element (which raises a TypeError because strings cannot index lists) to simply assigning the loop variable itself. This eliminates the exception entirely, so no output is produced where three TypeErrors were previously printed. The behavior differs because the original code intentionally caused and caught errors, while the fix suppresses them by altering the logic inside the try block. Thus, the transformation is not semantics-preserving—it changes what the program does, not just how it expresses it. The label "safe" is incorrect in this context.
Reproduce
- file
prog.py(the before program)- minimized program
- r2-p004.py
- evidence sheet
- r2-p004.md
- regression fixture
- r2-p004.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 · ruff PLR1736 variable shadowing · enumerate loop duplicate variables · list indexing with non-integer
- related astral-sh/ruff/issues/29422 umbrella issue listing PLR1736 among many rules but does not describe this specific shadowed-variable construct
- related astral-sh/ruff/issues/25182 tracks additional false positives for PLR1736 but focuses on dict iteration, not shadowed loop variables
- related astral-sh/ruff/issues/12594 PLR1736 defect about custom start index in enumerate, different construct from shadowed loop variables
- related astral-sh/ruff/issues/9010 autofix conflict between PLR1736 and FURB148, different root cause than shadowed-variable rewrite
- duplicate astral-sh/ruff/issues/8969 explicitly reports PLR1736 yields invalid suggestion and unsafe fix that changes semantics on shadowed loop variables like `for i, i in enumerate(...)`
Details
- program
- Variable capture due to name shadowing in enumerate
- hazard
- If the loop variable is named identically to the list (e.g., `for lst, lst in enumerate(lst): lst[lst]`), the fix risks incorrect variable capture due to name shadowing.
- oracle
stdout before: TypeError: string indices must be integers, not 'str' TypeError: string indices must be integers, not 'str' TypeError: string indices must be integers, not 'str' stdout after:- run
- 2026-10-17T21-04-33-755Z-llwi-ruff-PLR1736
generated program (10 lines) and the fix's diff
--- orig.py 2026-10-17 17:05:01.732035658 -0400 +++ fixed.py 2026-10-17 17:05:01.900037542 -0400 @@ -4,7 +4,7 @@ # So original: lst[index] -> element at index # Fix: lst (element) -> which is a string, not indexable -> TypeError try: - result = lst[lst] # original: indexes the list with the element (string) -> error + result = lst # original: indexes the list with the element (string) -> error except Exception as e: print(f'{type(e).__name__}: {e}', end=' ') print()
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)
```