# ruff PLR1733: 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: PLR1733 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity high. The fix incorrectly assumes the loop variable 'k' refers to the outer dictionary's key, but the inner loop shadows 'k' with the inner dictionary's key. Replacing 'outer[k]' with 'v' uses the inner loop's value instead of the outer loop's key, changing a KeyError into silent wrong behavior.
- Program: minimized from 11 to 5 lines

## Reproducer

```python
outer = {'x': 10}
middle = {'y': 20}
for k, v in outer.items():          # outer k='x', v=10
    for k, v in middle.items():       # inner k='y', v=20 (shadows outer)
            x = outer[k]              # triggers PLR1733: outer['y']?? -> KeyError
```

## Commands

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

## Observed

```
exit 1 → 0
stderr before: KeyError: 'y'
stderr after: (none)
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:34:46.096345908 -0400
+++ fixed.py	2026-10-22 13:34:48.204381448 -0400
@@ -2,4 +2,4 @@
 middle = {'y': 20}
 for k, v in outer.items():          # outer k='x', v=10
     for k, v in middle.items():       # inner k='y', v=20 (shadows outer)
-            x = outer[k]              # triggers PLR1733: outer['y']?? -> KeyError
+            x = v              # triggers PLR1733: outer['y']?? -> KeyError
```

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

The original code uses `k` from the inner loop to index into `outer`, which shadows the outer `k`. After fixing, it incorrectly replaces `outer[k]` with `v`, where `v` comes from the inner loop (`'y'`), but this does not replicate the intended access—it changes the meaning entirely, causing different behavior despite avoiding the error.

## Upstream search

Queries: "PLR1733 fix", "PLR1733 variable shadowing nested loops", "PLR1733 dictionary key access loop variables", "PLR1733 unused loop variable replacement"

- related: https://github.com/astral-sh/ruff/issues/25182
  same rule PLR1733 but different construct (for-else clause vs nested loop variable shadowing)
- related: https://github.com/astral-sh/ruff/issues/29422
  same rule PLR1733 mentioned among other fix bugs but no detail on this construct
- related: https://github.com/astral-sh/ruff/issues/25150
  same rule PLR1733 false positive but different construct (for-else clause vs nested loop variable shadowing)

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

- [github, open] Additional false positives in `PLR1733` and `PLR1736` — https://github.com/astral-sh/ruff/issues/25182
- [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, 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] PLR1733 false positive — https://github.com/astral-sh/ruff/issues/25150
- [github, closed] Pack of fuzzer Autofix/Infinite loop errors [2] — https://github.com/astral-sh/ruff/issues/8402

</details>
