fixhunt

ruff PERF101

labelled unknown
Runs / 2026-10-17T20-46-53-970Z-v1l0-ruff-PERF101ruff 0.17.12026-10-17 20:46 UTC8 programs × 2 round(s)16 programs, 0 fired, 0 fixed, 0 findings, 1 rejectedmodel cost $0.0027

Analysis Nemotron 3 Super

Flags redundant list() calls around iterables in for-loops.

Fix: Remove the list() constructor call while preserving its argument expression inside the for-loop header.

8 hazards
  • Rewriting list(expr) to expr changes behavior if expr has side effects evaluated multiple times due to iteration, as list() evaluates expr once before looping.
  • If expr is a generator, list() consumes it entirely while direct iteration may leave it partially consumed after loop break/continue.
  • When expr is an iterator, list() creates a snapshot; removing it risks mutation during iteration affecting results.
  • If expr returns a non-iterable, list() raises TypeError eagerly while direct iteration defers error until first iteration attempt.
  • In nested loops, removing list() may alter scoping if expr uses variables modified in outer loop iterations.
  • The fix drops any whitespace or formatting inside list() parentheses, potentially altering readability but not semantics.
  • If expr contains a trailing comma making it a tuple, list() treats it as single argument while removal may misparse in rare edge cases (though unlikely).
  • When expr is a call to a function returning self or list subclass, list() may copy while direct iteration uses original, affecting identity checks.

Programs

idresulttitlehazard
r1-p001silent prediction offWhitespace normalizationRule removes internal whitespace/formatting in list(), though this does not affect execution.
r1-p002silentRuntime type annotation evaluationlist() call inside annotation context triggers NameError if undefined; removing it changes timing/scope.
r1-p003silent prediction offPath behavior differenceslist(os.path.iterdir()) vs direct iteration when dealing with broken symlinks or missing dirs.
r1-p004silent prediction offException handling interactionRemoving list() changes when StopIteration is raised during iteration, affecting else/finally.
r1-p005silent prediction offGenerator consumption differencelist() exhausts generator immediately; direct iteration allows early break leaving state.
r1-p006silent prediction offIdentity with self-returning callablelist() creates copy; direct iteration uses original, affecting 'is' checks on elements.
r1-p007silent prediction offAttribute descriptor side effectsAccessing .attr triggers __get__; list() calls it once, direct iteration may call multiple times.
r1-p008silentAsync generator interactionlist() on async generator invalid without await; direct iteration requires async for. list() cannot be used here, so rule should not fire -- testing near-miss.
r2-p001silent prediction offContext manager non-file objectcontext managers that are not files, objects with write() but no close()
r2-p002invalidBytes vs str encoding newlinebytes vs str, encoding and newline handling, text vs binary modes
r2-p003silent prediction offMutable default arguments aliasingmutable default arguments and aliasing after a rewrite
r2-p004silent prediction offFunction returning self or list subclassWhen expr is a call to a function returning self or list subclass, list() may copy while direct iteration uses original, affecting identity checks.
r2-p005silent prediction offIterator mutation during iterationWhen expr is an iterator, list() creates a snapshot; removing it risks mutation during iteration affecting results.
r2-p006silent prediction offClass attributes descriptors side effectsclass attributes vs instance attributes, descriptors, properties with side effects
r2-p007silentType annotations evaluated at runtimetype annotations evaluated at runtime, typing-only imports
r2-p008silent prediction offDict ordering duplicate keys hash eqdict ordering, duplicate keys, __hash__/__eq__ overrides, sets

Sources

r1-p001 · Whitespace normalization
1for _ in list( range ( 5 ) ):
2 print(_)
0
1
2
3
4
r1-p002 · Runtime type annotation evaluation
1def f(): pass
2T = list[int]
3for x in T:
4 print(x)
*list[int]
r1-p003 · Path behavior differences
1import os
2os.makedirs('tmp', exist_ok=True)
3with open('tmp/file', 'w') as f: f.write('x')
4os.symlink('tmp/file', 'tmp/link')
5os.unlink('tmp/file')
6try:
7 for p in list(os.listdir('tmp')):
8 print('list:', p)
9except Exception as e:
10 print(type(e).__name__, e)
11finally:
12 import shutil
13 shutil.rmtree('tmp', ignore_errors=True)
list: link
r1-p004 · Exception handling interaction
1def gen():
2 yield 1
3 raise ValueError('bad')
4g = gen()
5try:
6 for x in list(g):
7 print(x)
8 print('else')
9except ValueError as e:
10 print('caught:', e)
11else:
12 print('no except')
13finally:
14 print('finally')
caught: bad
finally
r1-p005 · Generator consumption difference
1def gen():
2 for i in range(5):
3 yield i
4g = gen()
5for x in list(g):
6 if x == 2:
7 break
8 print('loop:', x)
9print('remaining:', list(g))
loop: 0
loop: 1
remaining: []
r1-p006 · Identity with self-returning callable
1class ListLike(list):
2 def __iter__(self):
3 return super().__iter__()
4L = ListLike([1,2])
5for x in list(L):
6 print('copy:', x is L[0])
7for x in L:
8 print('direct:', x is L[0])
copy: True
copy: False
direct: True
direct: False
r1-p007 · Attribute descriptor side effects
1class Attr:
2 def __get__(self, obj, owner):
3 print('get')
4 return [1,2]
5class Obj:
6 attr = Attr()
7O = Obj()
8for x in list(O.attr):
9 print('list iter:', x)
10for x in O.attr:
11 print('direct iter:', x)
get
list iter: 1
list iter: 2
get
direct iter: 1
direct iter: 2
r1-p008 · Async generator interaction
1async def agen():
2 yield 1
3 yield 2
4async def main():
5 try:
6 for x in list(agen()):
7 print(x)
8 except TypeError as e:
9 print('expected:', type(e).__name__, e)
10import asyncio
11asyncio.run(main())
expected: TypeError 'async_generator' object is not iterable
r2-p001 · Context manager non-file object
1class Ctx:
2 def __enter__(self):
3 return self
4 def __exit__(self, *exc):
5 pass
6 def write(self, x):
7 self.last = x
8ctx = Ctx()
9s = []
10for x in list(ctx):
11 ctx.write(x)
12 s.append(('written', ctx.last))
13print(s)
r2-p002 · Bytes vs str encoding newline (generated program does not parse: Traceback (most recent call last):)
1data = b'a
2b\r
3c
4'
5lines = []
6for line in list(data):
7 lines.append(chr(line))
8print(''.join(lines))
r2-p003 · Mutable default arguments aliasing
1def f(lst=[]):
2 lst.append(1)
3 return lst
4g = []
5for x in list(f()):
6 g.append(x)
7print(len(g), g)
1 [1]
r2-p004 · Function returning self or list subclass
1class MyList(list):
2 pass
3def get_self():
4 return MyList([1, 2])
5lst = get_self()
6for x in list(lst):
7 print(x is lst[0])
True
False
r2-p005 · Iterator mutation during iteration
1def gen():
2 yield 1
3 yield 2
4 yield 3
5it = gen()
6out = []
7for x in list(it):
8 out.append(x)
9 try:
10 next(it)
11 except StopIteration:
12 pass
13print(out)
[1, 2, 3]
r2-p006 · Class attributes descriptors side effects
1class Desc:
2 def __get__(self, obj, objtype):
3 self.calls += 1
4 return [self.calls]
5 def __init__(self):
6 self.calls = 0
7class Obj:
8 attr = Desc()
9obj = Obj()
10results = []
11for x in list(obj.attr):
12 results.append(x)
13print(results)
[1]
r2-p007 · Type annotations evaluated at runtime
1from typing import List
2L: List[int] = [1, 2]
3for x in L:
4 print(x)
1
2
r2-p008 · Dict ordering duplicate keys hash eq
1class BadHash:
2 def __init__(self, val):
3 self.val = val
4 def __hash__(self):
5 return 0
6 def __eq__(self, other):
7 return isinstance(other, BadHash) and self.val == other.val
8d = {BadHash(1): 'a', BadHash(2): 'b'}
9for k in list(d):
10 print(k.val)
1
2