# ruff SIM911: 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: SIM911 (tool labels the fix: unknown, this fix reported as safe)
- Oracle: fix-changes-behavior
- Judge (Nemotron 3 Ultra, advisory): real, severity high. The rule rewrites `zip(d.keys(), d.values())` to `d.items()`, but `zip` returns a reusable iterator while `dict.items()` returns a view that reflects the dictionary's current state. In the program, the view is consumed by the for-loop, so `list(zipped)` afterwards yields the items, whereas the original exhausted zip iterator yields an empty list. This is a silent change in runtime behavior for plausible code.
- Program: minimized from 13 to 5 lines

## Reproducer

```python
d = {'a': 1, 'b': 2}
zipped = zip(d.keys(), d.values())
for k, v in zipped:
    s = f'{k!r}:{v!r}'
print(repr(list(zipped)))
```

## Commands

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

## Observed

```
stdout before:
[]
stdout after:
[('a', 1), ('b', 2)]
```

## Diff applied by the fix

```diff
--- orig.py	2026-10-22 13:29:23.939936549 -0400
+++ fixed.py	2026-10-22 13:29:26.602981043 -0400
@@ -1,5 +1,5 @@
 d = {'a': 1, 'b': 2}
-zipped = zip(d.keys(), d.values())
+zipped = d.items()
 for k, v in zipped:
     s = f'{k!r}:{v!r}'
 print(repr(list(zipped)))
```

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

The original `zip` creates an iterator consumed by the loop; afterwards it’s exhausted, so converting it to a list yields []. Replacing it with `dict.items()` returns a view that remains reusable—iterating over it does not consume the view itself—so the subsequent `list(zipped)` captures all items, changing the output from [] to [('a', 1), ('b', 2)]. This alters program behavior, making the rewrite unsafe.

## Upstream search

Queries: "SIM911 fix", "SIM911 dict keys values zip", "Ruff lint zip dictionary iteration", "Rule SIM911 replace zip with items"

- related: https://github.com/astral-sh/ruff/issues/18775
  SIM910/SIM911 fix deletes comments inside the get call
- related: https://github.com/astral-sh/ruff/issues/18778
  SIM911 false positive when methods have arguments that get dropped by .items()
- related: https://github.com/astral-sh/ruff/issues/18776
  SIM911 fix causes syntax error due to missing parentheses
- related: https://github.com/astral-sh/ruff/issues/11125
  SIM911 false positive on non-zip attribute calls like plt.bar(dict.keys(), dict.values())
- related: https://github.com/astral-sh/ruff/issues/9319
  original implementation of SIM911 rule for zip(dict.keys(), dict.values()) → dict.items()
- related: https://github.com/astral-sh/ruff/issues/18777
  SIM910/SIM911 false negative when variable is named dict

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

- [github, closed] unused-function-argument not silenced by prefixed underscore if variable name is "次" — https://github.com/astral-sh/ruff/issues/28721
- [github, closed] [flake8-simplify] SIM910/SIM911 can delete comments — https://github.com/astral-sh/ruff/issues/18775
- [github, closed] [flake8-simplify] SIM911 false positive when methods have args — https://github.com/astral-sh/ruff/issues/18778
- [github, closed] [flake8-simplify] SIM911 fix causes syntax error — https://github.com/astral-sh/ruff/issues/18776
- [github, closed] SIM911 false positive (with bad autofix) on non-`zip` attribute calls — https://github.com/astral-sh/ruff/issues/11125
- [github, closed] Format breaks f-string with literal strings inside (versions 0.3.0 and 0.3.1) — https://github.com/astral-sh/ruff/issues/10273
- [github, closed] Implement new SIM rule SIM911: `zip(dict.keys(), dict.values()) → dict.items()` — https://github.com/astral-sh/ruff/issues/9319
- [tavily] [flake8-simplify] SIM910/SIM911 false negative if variable is named dict · Issue #18777 · astral-sh/ruff · GitHub — https://github.com/astral-sh/ruff/issues/18777
- [github, open] Feature: Port Sonar's Python scanner checks — https://github.com/astral-sh/ruff/issues/4935
- [tavily] B909 misses dict.keys() deletion · Issue #16865 · astral-sh/ruff — https://github.com/astral-sh/ruff/issues/16865

</details>
