fixhunt

ruff TC005: fix changes program behavior

fix-changes-behaviorlabelled safereal · highduplicate
Findings / 2026-10-17T20-39-34-299Z-g1ez-ruff-TC005 / r1-p005ruff 0.17.18 → 4 lines2026-10-17 20:39 UTC

Hypothesis Nemotron 3 Super predicted to fire fired 1×

generators vs lists, iterators consumed once, lazy vs eager evaluation

Program

before
1def gen():
2 if TYPE_CHECKING:
3 pass
4it = gen()
after
1def gen():
2 pass
3it = gen()

Output

stdout beforeexit 1
(no stdout)
NameError: name 'TYPE_CHECKING' is not defined
stdout afterexit 0
(no stdout)
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:` guard but leaves a `pass` statement, changing the code from a no-op (when TYPE_CHECKING is undefined) to an unconditional `pass`. This alters runtime behavior by eliminating the NameError that occurred when evaluating the undefined `TYPE_CHECKING` name, which is a silent change in program semantics for plausible code that relies on the guard to avoid runtime errors.

Explanation Nemotron 3 Super unverified

The original function contains a conditional that references `TYPE_CHECKING`, which raises a `NameError` when executed because the variable is undefined; this error prevents assignment to `it`. After rewriting, the conditional is removed and replaced with unconditional `pass`, so calling `gen()` succeeds without error and assigns `None` to `it`. Thus, the fix changes behavior by eliminating a runtime exception that was present in the original code.

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 TC005 --fix prog.py
python3 prog.py

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

TC005 fix · ruff TC005 conditional block removal · ruff TYPE_CHECKING guard elimination · ruff unused import cleanup

  • duplicate astral-sh/ruff/issues/28868 same TC005 empty-type-checking-block fix removing an if TYPE_CHECKING: pass block and causing a NameError
  • related astral-sh/ruff/issues/15681 same TC00x family but about false positives with manual TYPE_CHECKING and __future__.annotations
  • related astral-sh/ruff/issues/13929 detect empty conditional statements after import removal, similar empty-block problem but different trigger

Details

program
Generator vs list: iterator consumed once
hazard
generators vs lists, iterators consumed once, lazy vs eager evaluation
oracle
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 (8 lines) and the fix's diff
1def gen():
2 if TYPE_CHECKING:
3 pass
4 yield 1
5 yield 2
6it = gen()
7print(next(it))
8print(list(it)) # second consumption: should be [2] if gen() is lazy; if broken, may be [] or error
--- orig.py	2026-10-17 16:39:43.505847865 -0400
+++ fixed.py	2026-10-17 16:39:43.895865110 -0400
@@ -1,6 +1,4 @@
 def gen():
-    if TYPE_CHECKING:
-        pass
     yield 1
     yield 2
 it = gen()
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)