ruff TC005: fix changes program behavior
Hypothesis Nemotron 3 Super predicted to fire fired 1×
mutable default arguments and aliasing after a rewrite
Program
Output
(no stdout) NameError: name 'TYPE_CHECKING' is not defined
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
- related astral-sh/ruff/issues/28868 same rule TC005 but different construct (empty block after import removal vs undefined TYPE_CHECKING)
- related astral-sh/ruff/issues/15681 same TYPE_CHECKING detection logic but different construct (manual False assignment vs undefined name)
- related astral-sh/ruff/pull/16669 same TC005 rule and TYPE_CHECKING block detection logic, but PR changes what counts as a type-checking block
- related astral-sh/ruff/issues/11368 same TCH/TC family, autofix deletes else block removing code, similar over-deletion risk
- related astral-sh/ruff/issues/15526 same TYPE_CHECKING block context, but about self-assignment to silence unused import
- related astral-sh/ruff/issues/16176 same TC003 rule and TYPE_CHECKING = False handling, different construct
- related astral-sh/ruff/issues/9197 same TCH rules moving imports into TYPE_CHECKING blocks, but different failure mode
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
--- 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)