ruff F632: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
If x is a string literal like 'hello', 'x is "hello"' may be True due to interning, but 'x == "hello"' is also True—so no behavioral change, but the fix is still applied; however, relying on interning
Program
Output
interned /w/prog.py:2: SyntaxWarning: "is" with 'str' literal. Did you mean "=="?
interned
- fired
- 1 before · 0 after
- runs
- each version twice, same file name, no network
Judge Nemotron 3 Ultra advisory intended-change · low
The rule F632 explicitly rewrites identity comparisons (`is`) against literals to value comparisons (`==`) because `is` checks object identity, which is unreliable for literals. The observed change—removal of the SyntaxWarning and the program printing 'interned'—is exactly the semantic change the rule documents as its purpose. The program's behavior changes from a warning and no output to no warning and output, which is the intended fix.
Explanation Nemotron 3 Super unverified
The original uses `is` to test object identity; due to string interning in CPython, `'hello'` may be reused so `x is 'hello'` can evaluate True. Replacing it with `==` changes the check from identity to value equality—while both often yield True for identical literals, they differ when strings are constructed separately or via non-interning operations, making the transformation unsafe as it alters semantic intent.
Reproduce
- file
prog.py(the before program)- minimized program
- r2-p005.py
- evidence sheet
- r2-p005.md
- regression fixture
- r2-p005.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 identity comparison string literals · Ruff rule F632 is vs equals strings · Fix identity check to equality string
- related astral-sh/ruff/issues/12518 Same rule F632 but a different construct: the fix incorrectly rewrites `False == 0` (bool-int comparison) instead of a string literal comparison.
- related astral-sh/ruff/issues/11736 Same rule F632 but a different cause: the fix panics on malformed source (`0.0is 64`) rather than rewriting a valid string `is` comparison.
- related astral-sh/ruff/issues/9374 Same rule F632 but a different defect: an infinite loop toggling between `==` and `is` on a chained comparison, not a simple string literal.
- related astral-sh/ruff/issues/8589 Same rule F632 but a different construct: requests catching `variable is []` (list literal) instead of a string literal.
- related astral-sh/ruff/issues/6891 Same rule F632 but a different defect: infinite loop between E712 and F632 on bytes join, not a string `is` comparison.
- related astral-sh/ruff/issues/1057 Same rule F632 but a different cause: fix fails to extract CST on `value % 2 is 0` (int modulo), not a string literal.
- related astral-sh/ruff/issues/4560 Same rule F632/E712 but a different construct: fix incorrectly rewrites `triggered == False` (bool comparison) instead of a string literal.
Details
- program
- String Interning Safety
- hazard
- If x is a string literal like 'hello', 'x is "hello"' may be True due to interning, but 'x == "hello"' is also True—so no behavioral change, but the fix is still applied; however, relying on interning
- oracle
stderr before: /w/prog.py:2: SyntaxWarning: "is" with 'str' literal. Did you mean "=="? stderr after: (none)- run
- 2026-10-17T20-54-08-790Z-5ytj-ruff-F632
generated program (9 lines) and the fix's diff
--- orig.py 2026-10-17 16:54:37.320965996 -0400 +++ fixed.py 2026-10-17 16:54:37.516969031 -0400 @@ -1,5 +1,5 @@ x = 'hello' -if x is 'hello': +if x == 'hello': print('interned') else: print('not interned')
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/)