ruff F632: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
If x is a property that returns a new list on each access, 'x is []' is always False, and 'x == []' may be True
Program
Output
False
True
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory intended-change · low
The rule rewrites 'is' to '==' for literal comparisons because identity checks against literals are unreliable and will become SyntaxWarnings in Python 3.8. The program's comment acknowledges the original 'is []' comparison always returns False due to new list creation, while the fixed '== []' correctly returns True when the container's data property returns an empty list, demonstrating the intended semantic change from identity to value comparison.
Explanation Nemotron 3 Super unverified
The original expression `c.data is []` checks object identity; since `[]` creates a new empty list on each call to `.data`, it never matches the newly created literal in the condition, so the result is always False. After rewriting to `c.data == []`, equality compares values: both sides evaluate to empty lists with identical contents, yielding True despite being distinct objects. Thus the change from identity (`is`) to equality (`==`) alters the program’s observable output.
Reproduce
- file
prog.py(the before program)- minimized program
- r1-p006.py
- evidence sheet
- r1-p006.md
- regression fixture
- r1-p006.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 F632 --fix prog.py python3 prog.py
Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra
F632 fix · F632 property returns new mutable object · is comparison against literal list in property accessor · identity check on freshly created container instance
- related astral-sh/ruff/issues/12518 Same rule F632, but defect involves False == 0 comparison, not identity check against a fresh list literal.
- related astral-sh/ruff/issues/11736 Same rule F632, but defect is a panic/crash on invalid syntax, not a behavior-changing fix.
- related astral-sh/ruff/issues/9374 Same rule F632, but defect is an infinite loop between == and is on chained comparisons, not a fresh-list identity check.
- duplicate astral-sh/ruff/issues/8589 Explicitly titled 'Catch variable is []' — the same F632 rewrite (is -> ==) on a fresh list literal from a property/accessor.
- related astral-sh/ruff/issues/6891 Same rules F632/E712, but defect is an infinite loop on a generator expression, not a fresh-list identity check.
- related astral-sh/ruff/issues/1057 Same rule F632, but defect is a crash extracting CST from a lambda default value from a lambda default, not a behavior-changing fix.
Details
- program
- Property Returns New List
- hazard
- If x is a property that returns a new list on each access, 'x is []' is always False, and 'x == []' may be True
- oracle
stdout before: False stdout after: True- run
- 2026-10-17T20-54-08-790Z-5ytj-ruff-F632
generated program (12 lines) and the fix's diff
--- orig.py 2026-10-17 16:54:26.812802623 -0400 +++ fixed.py 2026-10-17 16:54:26.974805153 -0400 @@ -7,6 +7,6 @@ def set_data(self, val): self._data = val c = Container() -print(c.data is []) # Always False (new list each time) +print(c.data == []) # Always False (new list each time) print(c.data == []) # True → fix changes behavior # Before: identity → False; after: equality → True
rule documentation given to the models
# is-literal (F632)
Derived from the **Pyflakes** linter.
Fix is always available.
## What it does
Checks for `is` and `is not` comparisons against literals, like integers,
strings, or lists.
## Why is this bad?
The `is` and `is not` comparators operate on identity, in that they check
whether two objects are the same object. If the objects are not the same
object, the comparison will always be `False`. Using `is` and `is not` with
constant literals often works "by accident", but are not guaranteed to produce
the expected result.
As of Python 3.8, using `is` and `is not` with constant literals will produce
a `SyntaxWarning`.
This rule will also flag `is` and `is not` comparisons against non-constant
literals, like lists, sets, and dictionaries. While such comparisons will
not raise a `SyntaxWarning`, they are still likely to be incorrect, as they
will compare the identities of the objects instead of their values, which
will always evaluate to `False`.
Instead, use `==` and `!=` to compare literals, which will compare the
values of the objects instead of their identities.
## Example
```python
x = 200
if x is 200:
print("It's 200!")
```
Use instead:
```python
x = 200
if x == 200:
print("It's 200!")
```
## References
- [Python documentation: Identity comparisons](https://docs.python.org/3/reference/expressions.html#is-not)
- [Python documentation: Value comparisons](https://docs.python.org/3/reference/expressions.html#value-comparisons)
- [_Why does Python log a SyntaxWarning for ‘is’ with literals?_ by Adam Johnson](https://adamj.eu/tech/2020/01/21/why-does-python-3-8-syntaxwarning-for-is-literal/)