fixhunt

ruff RUF046: fix changes program behavior

fix-changes-behaviorlabelled safeintrospection-only · lowrelated
Findings / 2026-10-17T21-45-18-816Z-cile-ruff-RUF046 / r1-p005ruff 0.17.19 → 3 lines2026-10-17 21:45 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

Rewriting int(5+3) may break formatters that rely on the int() call for alignment or style metrics, even if value unchanged.

Program

before
1import inspect
2src = inspect.getsource(lambda: int(5 + 3))
3print('Source length of int(5+3):', len(src.strip()))
after
1import inspect
2src = inspect.getsource(lambda: (5 + 3))
3print('Source length of int(5+3):', len(src.strip()))

Output

stdout beforeexit 0
Source length of int(5+3): 43
stdout afterexit 0
Source length of int(5+3): 40
fired
1 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory introspection-only · low

The fix removes the redundant `int()` call from the lambda's source code, which changes the text returned by `inspect.getsource`. This is purely a source-code introspection difference; the runtime behavior of the lambda (returning 8) is unchanged.

Explanation Nemotron 3 Super unverified

The original lambda calls `int` on the result of `5 + 3`, producing integer value 8; its source includes the call to `int`. After rewriting, the lambda returns only the expression `(5 + 3)` without applying `int`, so its source text omits those characters, changing the string returned by `inspect.getsource`. Consequently, stripping whitespace yields a shorter string, reducing its length from 43 to 40, which alters the printed output. The transformation removes a function call that affects the lambda’s source representation, violating semantic equivalence under `inspect.getsource`.

Reproduce

file
prog.py (the before program)
minimized program
r1-p005.py
evidence sheet
r1-p005.md
regression fixture
r1-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 RUF046 --fix prog.py
python3 prog.py

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

RUF046 fix · RUF046 lambda call to builtin · inspect.getsource lambda simplification · ruff remove redundant constructor

  • related astral-sh/ruff/issues/15263 RUF046 fix defect involving newline before call expression's opening parenthesis, different construct than lambda-wrapped int().
  • related astral-sh/ruff/issues/15226 RUF046 fix crash/behavior change when cast expression contains a newline, different trigger than lambda context.
  • related astral-sh/ruff/issues/14793 Design complaint that RUF046 handles both round() and int() together, not the specific lambda int() removal bug.

Details

program
Formatting Tool Dependency
hazard
Rewriting int(5+3) may break formatters that rely on the int() call for alignment or style metrics, even if value unchanged.
oracle
stdout before: Source length of int(5+3): 43 stdout after: Source length of int(5+3): 40
run
2026-10-17T21-45-18-816Z-cile-ruff-RUF046
generated program (9 lines) and the fix's diff
1# This line's length affects flake8 or black line length scoring
2val = int(5 + 3) # kept for formatting
3print('Value:', val)
4# If removed: 'val = 5 + 3' is shorter; tools may reformat differently
5# We show the line length as proxy
6import inspect
7import textwrap
8src = inspect.getsource(lambda: int(5 + 3))
9print('Source length of int(5+3):', len(src.strip()))
--- orig.py	2026-10-17 17:45:34.478890819 -0400
+++ fixed.py	2026-10-17 17:45:34.693889435 -0400
@@ -1,9 +1,9 @@
 # This line's length affects flake8 or black line length scoring
-val = int(5 + 3)  # kept for formatting
+val = 5 + 3  # kept for formatting
 print('Value:', val)
 # If removed: 'val = 5 + 3' is shorter; tools may reformat differently
 # We show the line length as proxy
 import inspect
 import textwrap
-src = inspect.getsource(lambda: int(5 + 3))
+src = inspect.getsource(lambda: (5 + 3))
 print('Source length of int(5+3):', len(src.strip()))
rule documentation given to the models
# unnecessary-cast-to-int (RUF046)

Derived from the **Ruff-specific rules** linter.

Fix is always available.

## What it does
Checks for `int` conversions of values that are already integers.

## Why is this bad?
Such a conversion is unnecessary.

## Known problems
This rule may produce false positives for `round`, `math.ceil`, `math.floor`,
and `math.trunc` calls when values override the `__round__`, `__ceil__`, `__floor__`,
or `__trunc__` operators such that they don't return an integer.

## Example

```python
int(len([]))
int(round(foo, None))
```

Use instead:

```python
len([])
round(foo)
```

## Fix safety
The fix for `round`, `math.ceil`, `math.floor`, and `math.truncate` is unsafe
because removing the `int` conversion can change the semantics for values
overriding the `__round__`, `__ceil__`, `__floor__`, or `__trunc__` dunder methods
such that they don't return an integer.