fixhunt

ruff TC005: fix changes program behavior

fix-changes-behaviorlabelled safereal · highrelated
Findings / 2026-10-17T20-39-34-299Z-g1ez-ruff-TC005 / r1-p003ruff 0.17.19 → 6 lines2026-10-17 20:39 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

mutable default arguments and aliasing after a rewrite

Program

before
1def f(a=None):
2 if a is None:
3 a = []
4 if TYPE_CHECKING:
5 pass
6print(f())
after
1def f(a=None):
2 if a is None:
3 a = []
4print(f())

Output

stdout beforeexit 1
(no stdout)
NameError: name 'TYPE_CHECKING' is not defined
stdout afterexit 0
None
fired
1 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory real · high

The fix removes the `if TYPE_CHECKING:` block without ensuring `TYPE_CHECKING` is imported from `typing`. The original code crashed with a NameError because `TYPE_CHECKING` was undefined; after the fix, the crash disappears and the function returns `None`. Since the documentation presents the rewrite as a safe removal of dead code but does not mention the required import, the fix changes runtime behavior from an error to silent success in plausible code.

Explanation Nemotron 3 Super unverified

The original function raises a NameError when called because `TYPE_CHECKING` is undefined outside type-checking contexts; this exception prevents execution from reaching the `print` statement. Removing the conditional block eliminates the error, allowing the function to return the default list `[]`, which is then printed. Thus, the rewrite changes behavior by suppressing an exception that altered program flow.

Reproduce

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

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

TC005 fix · TC005 mutable default argument · ruff TC005 list initialization pattern · fix removes unused TYPE_CHECKING block

Details

program
Mutable default argument aliased after rewrite
hazard
mutable default arguments and aliasing after a rewrite
oracle
stdout before: stdout after: None exit 1 → 0 stderr before: NameError: name 'TYPE_CHECKING' is not defined stderr after: (none)
run
2026-10-17T20-39-34-299Z-g1ez-ruff-TC005
generated program (9 lines) and the fix's diff
1def f(a=None):
2 if a is None:
3 a = []
4 if TYPE_CHECKING:
5 pass
6 a.append(1)
7 return a
8print(f())
9print(f())
--- orig.py	2026-10-17 16:39:42.534804899 -0400
+++ fixed.py	2026-10-17 16:39:42.912821638 -0400
@@ -1,8 +1,6 @@
 def f(a=None):
     if a is None:
         a = []
-    if TYPE_CHECKING:
-        pass
     a.append(1)
     return a
 print(f())
rule documentation given to the models
# empty-type-checking-block (TC005)

Derived from the **flake8-type-checking** linter.

Fix is always available.

## What it does
Checks for an empty type-checking block.

## Why is this bad?
The type-checking block does not do anything and should be removed to avoid
confusion.

## Example
```python
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    pass

print("Hello, world!")
```

Use instead:
```python
print("Hello, world!")
```

## References
- [PEP 563: Runtime annotation resolution and `TYPE_CHECKING`](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking)