fixhunt

ruff C405

labelled unknown
Runs / 2026-10-17T20-19-51-372Z-u23e-ruff-C405ruff 0.17.12026-10-17 20:19 UTC8 programs × 2 round(s)16 programs, 1 fired, 0 fixed, 0 findings, 2 rejectedmodel cost $0.0032

Analysis Nemotron 3 Super

Flags set() constructor called with a single list or tuple literal argument.

Fix: Rewrites set(L) where L is a list or tuple literal to {*L} if non-empty, otherwise set().

8 hazards
  • The rewrite drops inline or trailing comments attached to the set() call or its argument, as the autofix may not preserve comment nodes during AST transformation.
  • If the list or tuple literal contains mutable elements that are later modified, the resulting set may capture different object identities due to reconstruction via set literal, though values remain equal.
  • In rare cases involving custom __eq__ or __hash__ implementations, the order of element insertion during set literal construction could theoretically affect hash collision resolution, though final set equality is preserved.
  • If the argument is a tuple literal used elsewhere in the code (e.g., assigned to a variable), rewriting to a set literal severs that shared reference, potentially breaking aliasing expectations.
  • The autofix may incorrectly apply to set() calls generated via macros or code-generation tools where the list/tuple appears literal but is semantically dynamic, leading to incorrect static rewrites.
  • If the set() call is part of a larger expression where the original call's formatting or line breaks are significant (e.g., for diff tools or readability), the rewrite may alter whitespace in a way that breaks team formatting rules.
  • When the list or tuple literal contains duplicate elements, the set literal rewrite behaves identically, but intermediate steps in evaluation (like list creation) are skipped, which could matter in tracing or debugging contexts.
  • If the code relies on the set() constructor for its type (e.g., isinstance(x, set) after assignment), the rewrite still produces a set, so no behavioral change occurs—this hazard is included to emphasize that type preservation holds, unlike in unsafe cases.

Programs

idresulttitlehazard
r1-p001silent prediction offMutable Default Arguments AliasingRewriting `set([])` to `set()` removes explicit empty list creation, causing shared state across function calls when used as a mutable default.
r1-p002fired, no fixCustom __eq__ and Hash Collision ResolutionSet literal `{*L}` may insert elements in different order than `set(L)`, affecting internal hash table probing sequence even if final equality holds; this can surface in debugging or custom `__repr__`
r1-p003silentMacro-Generated Code MisinterpretationCode generation tools may produce `set([x for x in ...])` where the list comprehension looks literal but is semantically dynamic; rewriting to `{*[x for x in ...]}` is invalid syntax, causing parse fa
r1-p004silent prediction offDuplicate Elements and Intermediate Evaluation SkippedRewriting `set([1,1,2])` skips list creation, removing a potential breakpoint or trace point in debugging where the list's construction had side effects.
r1-p005silentGenerators Consumed OnceRewriting `set(generator)` is not attempted by the rule (correctly), but if mistakenly applied, `{*gen}` would consume the generator eagerly, whereas `set(gen)` does so lazily; here we show the rule c
r1-p006silent prediction offBytes vs Str Encoding and NewlinesRewriting `set([b'a', b'b'])` to `{*[b'a', b'b']}` is safe for bytes, but if the list were decoded strings with encoding-sensitive content, the rewrite doesn't change semantics—yet tracing list creati
r1-p007silent prediction offType Annotations Evaluated at RuntimeIf a list literal in a set() call is used in a forward reference resolved at runtime via `typing.get_type_hints()`, rewriting it to a set literal doesn't change the value, but the intermediate list mi
r1-p008invalidNon-File Context Managers with write()Rewriting `set([log_stream])` where `log_stream` is a context manager with `write()` but no `close()` doesn't affect resource safety, but if the list literal were part of a larger expression with side
r2-p001silent prediction offMutable List Literal Elements Modified After Set ConstructionIf the list or tuple literal contains mutable elements that are later modified, the resulting set may capture different object identities due to reconstruction via set literal, though values remain eq
r2-p002silent prediction offType Annotation Evaluated at Runtime Using Forward Referencetype annotations evaluated at runtime, typing-only imports
r2-p003silent prediction offTuple Literal Shared Reference Severed by RewriteIf the argument is a tuple literal used elsewhere in the code (e.g., assigned to a variable), rewriting to a set literal severs that shared reference, potentially breaking aliasing expectations.
r2-p004silent prediction offDict Ordering and Duplicate Keys in Set Construction via Listdict ordering, duplicate keys, __hash__/__eq__ overrides, sets
r2-p005silent prediction offAsync Generator Consumption Affected by Set Literal Rewriteasync def/await ordering, async generators
r2-p006silent prediction offCustom __eq__/__hash__ and Insertion Order in Set LiteralIn rare cases involving custom __eq__ or __hash__ implementations, the order of element insertion during set literal construction could theoretically affect hash collision resolution, though final set
r2-p007invalidBytes vs Str Encoding and Newline Handling in Set Literalbytes vs str, encoding and newline handling, text vs binary modes
r2-p008silent prediction offEvaluation Order and Side Effects in Set Argument Expressionevaluation order and side effects when expressions are merged, duplicated or deleted

Sources

r1-p001 · Mutable Default Arguments Aliasing
1def f(x=None):
2 if x is None:
3 x = []
4 s = set(x)
5 s.add(len(s))
6 return s
7print(f(), f())
{0} {0}
r1-p002 · Custom __eq__ and Hash Collision Resolution
1class A:
2 def __init__(self, v): self.v = v
3 def __hash__(self): return hash(self.v)
4 def __eq__(self, other): return isinstance(other, A) and self.v == other.v
5 def __repr__(self): return f'A({self.v})'
6a1, a2 = A(1), A(2)
7s = set([a1, a2])
8print(repr(s))
{A(1), A(2)}
r1-p003 · Macro-Generated Code Misinterpretation
1try:
2 exec("s = {[x for x in [1,2]]}")
3 print('no error')
4except SyntaxError as e:
5 print(type(e).__name__, str(e))
r1-p004 · Duplicate Elements and Intermediate Evaluation Skipped
1trace = []
2def make_list():
3 trace.append('list made')
4 return [1,1,2]
5s = set(make_list())
6print(''.join(trace), len(s))
list made 2
r1-p005 · Generators Consumed Once
1def gen():
2 yield 1
3 yield 2
4s = set(gen())
5print(''.join(str(x) for x in s))
12
r1-p006 · Bytes vs Str Encoding and Newlines
1data = [b'hello\n', b'world\n']
2trace = []
3class TrackedBytes(bytes):
4 def __new__(cls, b): trace.append(b); return super().__new__(cls, b)
5s = set(TrackedBytes(b) for b in data)
6print(''.join(trace), sorted(s))
r1-p007 · Type Annotations Evaluated at Runtime
1import typing
2T = list[int]
3def f() -> T:
4 return [1,2]
5s = set(f())
6print(type(s), s)
<class 'set'> {1, 2}
r1-p008 · Non-File Context Managers with write() (generated program does not parse: Traceback (most recent call last):)
1class LogStream:
2 def __init__(self): self.buf = []
3 def write(self, s): self.buf.append(s)
4 def __enter__(self): return self
5 def __exit__(self, *_:): pass
6with LogStream() as ls:
7 ls.write('x')
8 s = set([ls])
9 print(id(s), len(s))
r2-p001 · Mutable List Literal Elements Modified After Set Construction
1outer_list = []
2for i in range(2):
3 lst = [i]
4 outer_list.append(lst)
5 s = set(lst)
6 lst[0] = 99
7 print(f'i={i}, set={s}, lst={lst}')
i=0, set={0}, lst=[99]
i=1, set={1}, lst=[99]
r2-p002 · Type Annotation Evaluated at Runtime Using Forward Reference
1from __future__ import annotations
2def f() -> 'List[int]':
3 return [1, 2]
4s = set(f())
5print(f'set from annotation-resolved list: {s}')
6if hasattr(f.__annotations__['return'], '__class__'):
7 print('Annotation type:', f.__annotations__['return'].__class__)
set from annotation-resolved list: {1, 2}
Annotation type: <class 'str'>
r2-p003 · Tuple Literal Shared Reference Severed by Rewrite
1t = (1, 2)
2s = set(t)
3t = (3, 4) # reassign t
4print(f'set from original t: {s}')
5print(f't after reassignment: {t}')
6# s should still reflect (1,2), not (3,4)
set from original t: {1, 2}
t after reassignment: (3, 4)
r2-p004 · Dict Ordering and Duplicate Keys in Set Construction via List
1class BadDict:
2 def __init__(self, v):
3 self.v = v
4 def __hash__(self):
5 return hash(self.v)
6 def __eq__(self, other):
7 return isinstance(other, BadDict) and self.v == other.v
8l = [BadDict(1), BadDict(1)]
9s = set(l)
10print(f'Set size from duplicate BadDict: {len(s)}')
11print(f'Elements: {[x.v for x in s]}')
Set size from duplicate BadDict: 1
Elements: [1]
r2-p005 · Async Generator Consumption Affected by Set Literal Rewrite
1async def gen():
2 yield 1
3 yield 2
4async def main():
5 g = gen()
6 lst = [x async for x in g]
7 s = set(lst)
8 print(f'Set from async gen: {s}')
9import asyncio
10asyncio.run(main())
Set from async gen: {1, 2}
r2-p006 · Custom __eq__/__hash__ and Insertion Order in Set Literal
1class OrderSensitive:
2 def __init__(self, val, name):
3 self.val = val
4 self.name = name
5 def __hash__(self):
6 return hash(self.val)
7 def __eq__(self, other):
8 return isinstance(other, OrderSensitive) and self.val == other.val
9 def __repr__(self):
10 return f'OS({self.val},{self.name})'
11l = [OrderSensitive(1, 'a'), OrderSensitive(1, 'b')]
12s = set(l)
13print(f'Set contents: {s}')
14print(f'Length: {len(s)}')
Set contents: {OS(1,a)}
Length: 1
r2-p007 · Bytes vs Str Encoding and Newline Handling in Set Literal (generated program does not parse: Traceback (most recent call last):)
1l = [b'hello
2', b'world\r
3']
4s = set(l)
5print(f'Set of byte strings: {s}')
6for b in s:
7 print(f'Bytes: {b!r}, Decoded: {b.decode()}')
r2-p008 · Evaluation Order and Side Effects in Set Argument Expression
1side_effects = []
2def f():
3 side_effects.append(len(side_effects))
4 return [side_effects[-1]]
5s = set(f())
6print(f'Side effects log: {side_effects}')
7print(f'Set from f(): {s}')
8# If f() called twice due to rewrite, log would be [0,1]
Side effects log: [0]
Set from f(): {0}