fixhunt

ruff C408

labelled unknown
Runs / 2026-10-17T20-20-46-034Z-2zyw-ruff-C408ruff 0.17.12026-10-17 20:20 UTC8 programs × 2 round(s)16 programs, 8 fired, 0 fixed, 0 findings, 1 rejectedmodel cost $0.0025

Analysis Nemotron 3 Super

Flags unnecessary dict(), list(), or tuple() calls without arguments that can be replaced by empty literal syntax.

Fix: Replaces dict() with {}, list() with [], and tuple() with () when called with no arguments.

9 hazards
  • Rewriting dict() to {} may drop inline comments attached to the call expression if they are not preserved during AST transformation.
  • If dict is locally rebound (e.g., `dict = lambda: None`), replacing dict() with {} changes semantics because the literal invokes the built-in dict type, not the local binding.
  • In rare cases involving import hooks or metaprogramming that intercept built-in name resolution, replacing dict() with {} bypasses the hook, altering behavior.
  • If the code relies on the traceback showing a call to 'dict()' for debugging or logging, replacing it with {} removes that call frame, affecting diagnostic output.
  • When dict() appears in a string literal or comment (e.g., 'print("dict()")'), the autofix must not trigger, but a buggy implementation might erroneously modify such strings.
  • If dict() is used in a context where its return value is intentionally ignored for side effects (though dict() has none), replacing it with {} could mislead readers about intent, though no behavioral change occurs.
  • In code that is parsed and then executed via exec() or eval() with a restricted globals where dict is removed, replacing dict() with {} may succeed where the original would raise NameError, altering error behavior.
  • If the code depends on the exact bytecode or memory allocation pattern of calling dict() vs. using {} (e.g., for benchmarking or low-level optimization), the rewrite changes those characteristics.
  • When dict() appears in a DSL or code-generation context where the text 'dict()' is later interpreted by another system, replacing it with {} breaks downstream processing.

Programs

idresulttitlehazard
r1-p001fired, no fixCoercion with nested constructorsint/float/bool coercion, Decimal, division and rounding
r1-p002fired, no fixAsync generator exhaustion timingasync def/await ordering, async generators
r1-p003silent prediction offShadowed dict then restored global callshadowed builtins and names redefined later in the module
r1-p004fired, no fixPartial write from constructor reusefile modes and truncation, partial writes, non-str data passed to write
r1-p005fired, no fixWalrus in comprehension capturewalrus, comprehensions scoping, late binding in closures and lambdas
r1-p006fired, no fixBytecode difference via disassemblyIf the code depends on the exact bytecode or memory allocation pattern of calling dict() vs. using {} (e.g., for benchmarking or low-level optimization), the rewrite changes those characteristics.
r1-p007invalidDuplicate key survival in literal vs calldict ordering, duplicate keys, __hash__/__eq__ overrides, sets
r1-p008fired, no fixSide effect order in nested callevaluation order and side effects when expressions are merged, duplicated or deleted
r2-p001silent prediction offexec with restricted globals removing dictIn code that is parsed and then executed via exec() or eval() with a restricted globals where dict is removed, replacing dict() with {} may succeed where the original would raise NameError, altering e
r2-p002silent prediction offclass attribute descriptor with side effectclass attributes vs instance attributes, descriptors, properties with side effects
r2-p003fired, no fixtruthiness of custom __bool__/__len__truthiness of custom __bool__/__len__, None vs falsy, 'is' vs '=='
r2-p004silent prediction offlocal rebinding of dictIf dict is locally rebound (e.g., `dict = lambda: None`), replacing dict() with {} changes semantics because the literal invokes the built-in dict type, not the local binding.
r2-p005fired, no fixinline comment preservationRewriting dict() to {} may drop inline comments attached to the call expression if they are not preserved during AST transformation.
r2-p006silent prediction offasync function interactionasync def/await ordering, async generators
r2-p007silentpathlib vs os.path behaviorpathlib vs os.path behavior on relative paths, symlinks, missing files, bytes paths
r2-p008silent prediction offgenerator consumptiongenerators vs lists, iterators consumed once, lazy vs eager evaluation

Sources

r1-p001 · Coercion with nested constructors
1from decimal import Decimal
2x = float(int(round(float(dict()))))
3print(x)
r1-p002 · Async generator exhaustion timing
1async def gen():
2 yield await list().__repr__()
3async def main():
4 g = gen()
5 print(await g.__anext__())
6import asyncio
7asyncio.run(main())
r1-p003 · Shadowed dict then restored global call
1dict = lambda: {'shadow': True}
2x = dict()
3print(x)
4del dict
5x = dict()
6print(sorted(x.items()))
{'shadow': True}
[]
r1-p004 · Partial write from constructor reuse
1with open('tmp.bin', 'wb') as f:
2 f.write(bytes(list()))
3with open('tmp.bin', 'rb') as f:
4 print(f.read())
5import os
6os.remove('tmp.bin')
b''
r1-p005 · Walrus in comprehension capture
1fns = []
2for i in range(2):
3 if (x := list()) is not None:
4 fns.append(lambda: len(x))
5print([f() for f in fns])
[0, 0]
r1-p006 · Bytecode difference via disassembly
1import dis
2print('dict() bytecode:')
3dis.dis(lambda: dict())
4print('{} bytecode:')
5dis.dis(lambda: {})
dict() bytecode:
  3           RESUME                   0
              LOAD_GLOBAL              1 (dict + NULL)
              CALL                     0
              RETURN_VALUE
{} bytecode:
  5           RESUME                   0
              BUILD_MAP                0
              RETURN_VALUE
r1-p007 · Duplicate key survival in literal vs call (generated program is not deterministic)
1class BadHash:
2 def __hash__(self): return 1
3 def __eq__(self, o): return isinstance(o, BadHash)
4a = BadHash()
5b = BadHash()
6d = dict([(a, 1), (b, 2)])
7print(len(d), sorted(d.items()))
r1-p008 · Side effect order in nested call
1side = []
2def f():
3 side.append(1)
4 return dict()
5x = f()
6side.append(2)
7print(side, x)
[1, 2] {}
r2-p001 · exec with restricted globals removing dict
1g = {'__builtins__': {}}
2exec("x = dict()", g)
3print(type(x))
r2-p002 · class attribute descriptor with side effect
1class Desc:
2 def __get__(self, obj, owner):
3 print('Desc.get')
4 return []
5
6class A:
7 attr = Desc()
8
9a = A()
10print(type(a.attr))
11a.attr.append(1)
12print(type(A.attr))
Desc.get
<class 'list'>
Desc.get
Desc.get
<class 'list'>
r2-p003 · truthiness of custom __bool__/__len__
1class X:
2 def __len__(self):
3 return 1
4
5x = list()
6print(bool(x))
7x.append(X())
8print(bool(x))
False
True
r2-p004 · local rebinding of dict
1def f():
2 dict = lambda: None
3 x = dict()
4 y = {}
5 print(type(x), type(y))
6f()
<class 'NoneType'> <class 'dict'>
r2-p005 · inline comment preservation
1x = dict() # make empty
2print(type(x))
<class 'dict'>
r2-p006 · async function interaction
1async def g():
2 return []
3
4async def main():
5 x = await g()
6 print(type(x))
7
8import asyncio
9asyncio.run(main())
<class 'list'>
r2-p007 · pathlib vs os.path behavior
1import os
2import tempfile
3with tempfile.TemporaryDirectory() as d:
4 p = os.path.join(d, 'test')
5 with open(p, 'w') as f:
6 f.write('hi')
7 print(os.path.exists(p))
True
r2-p008 · generator consumption
1def gen():
2 yield 1
3 yield 2
4
5g = gen()
6print(list(g))
7print(list(g))
[1, 2]
[]