# ruff PLR1736: fix changes program behavior

Internal evidence sheet generated by fixhunt. Not an issue text. A human re-verifies, checks the duplicates
below, and writes the upstream report in their own words following the project's AI policy.

- Tool: ruff ruff 0.17.1
- Rule: PLR1736 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity 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.
- Program: minimized from 6 to 5 lines

## Reproducer

```python
lst = [10, 20]
for i, x in enumerate(lst):
    print(f'Before: lst[{i}]={lst[i]}, x={x}')
    if i == 0:
        lst = [99, 88]  # Rebinding in outer scope
```

## Commands

```sh
python3 prog.py
ruff check --preview --isolated --select PLR1736 --fix prog.py
python3 prog.py
```

## Observed

```
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
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:35:54.506500008 -0400
+++ fixed.py	2026-10-22 13:35:56.980541773 -0400
@@ -1,5 +1,5 @@
 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
```

## Why the rewrite is not equivalent (model draft, verify before use)

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.

## Upstream search

Queries: "PLR1736 fix", "PLR1736 f-string list indexing", "enumerate loop variable substitution", "list rebinding during iteration"

- related: https://github.com/astral-sh/ruff/issues/29422
  umbrella issue listing PLR1736 among many rules but no specific rebinding construct
- related: https://github.com/astral-sh/ruff/issues/25182
  tracks additional false positives for PLR1736 but does not describe rebinding of the iterated list
- related: https://github.com/astral-sh/ruff/issues/12594
  PLR1736 defect but about custom start index, not list rebinding
- related: https://github.com/astral-sh/ruff/issues/9010
  autofix conflict between PLR1736 and FURB148, different cause than rebinding
- duplicate: https://github.com/astral-sh/ruff/issues/8969
  exact same PLR1736 unsafe fix that changes semantics when the iterated list is rebound in the loop

<details><summary>All hits</summary>

- [github, open] A few more: missed reports vs flake8/pylint, plus two fix bugs (B012, F402, F823, SIM102, SIM401, PLW1641, PLR1736, PLW0406, N801, UP034) — https://github.com/astral-sh/ruff/issues/29422
- [github, open] Additional false positives in `PLR1733` and `PLR1736` — https://github.com/astral-sh/ruff/issues/25182
- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, open] Implement Pylint — https://github.com/astral-sh/ruff/issues/970
- [github, closed] PLR1736 does not account for custom start index — https://github.com/astral-sh/ruff/issues/12594
- [github, closed] Pack of fuzzer Autofix/Infinite loop errors [2] — https://github.com/astral-sh/ruff/issues/8402
- [github, closed] PLR1736 not implemented? — https://github.com/astral-sh/ruff/issues/8972
- [github, closed] Autofix conflict between `PLR1736` and `FURB148` — https://github.com/astral-sh/ruff/issues/9010
- [github, closed] `PLR1736` yields invalid suggestion and unsafe fix that changes semantics. — https://github.com/astral-sh/ruff/issues/8969
- [github, closed] C3001/C3002 Implemented? — https://github.com/astral-sh/ruff/issues/8973
- [github, open] [syntax-errors] Remaining syntax errors raised by the compiler — https://github.com/astral-sh/ruff/issues/17412

</details>
