fixhunt

ruff RET504

labelled unknown
Runs / 2026-10-17T20-32-23-657Z-hxhb-ruff-RET504ruff 0.17.12026-10-17 20:32 UTC8 programs × 2 round(s)16 programs, 5 fired, 0 fixed, 0 findings, 1 rejectedmodel cost $0.0028

Analysis Nemotron 3 Super

Flags redundant variable assignments where the assigned variable is returned immediately afterward.

Fix: Remove the assignment statement and replace the returned variable with the expression originally assigned to it.

12 hazards
  • Assignment inside a conditional block may skip execution when condition is false, but moving expression to return would evaluate it unconditionally.
  • Assignment inside a loop body may execute zero or multiple times, but returning the expression directly evaluates it once before loop entry.
  • Assignment inside a try block where finally reassigns the variable would lose the finally's effect on the returned value.
  • Assignment to a variable that is also read in a lambda or nested function defined later in the same scope would break closure capture.
  • Assignment to a variable that has the same name as an imported symbol would shadow the import only locally; removing the assignment could cause the return to use the imported value instead.
  • Assignment with a walrus operator (:=) inside a list comprehension or other comprehension changes the iteration semantics if the variable is used elsewhere in the comprehension.
  • Assignment to a variable that is annotated with a type comment or type hint would drop the annotation if the assignment is removed, affecting static analysis.
  • Assignment that includes a delayed evaluation via a property setter would lose the setter invocation if the expression is returned directly.
  • Assignment that occurs after a side-effecting expression (e.g., function call) but before a return would still have executed the side effect; removing the assignment does not drop the side effect, but if the expression is moved into the return, the side effect remains—however, if the expression is duplicated due to common subexpression assumptions, it could be evaluated twice.
  • Assignment where the expression is a yield or yield-from expression would change the generator's behavior if the yield is moved into a return statement.
  • Assignment where the variable is deleted later in the same block (e.g., 'del x') would cause a NameError if the return uses the variable after deletion, but removing the assignment avoids the deletion error—however, the fix assumes no such deletion exists between assignment and return, so this hazard is mitigated by the rule's pattern but still relevant if the linter misses intervening code.
  • Assignment that is the only statement in a block that ends with a return, but the block is part of a multi-line statement (e.g., continuation lines), could break parsing if the fix removes indentation incorrectly.

Programs

idresulttitlehazard
r1-p001silent prediction offConditional block skipAssignment inside a conditional block may skip execution when condition is false, but moving expression to return would evaluate it unconditionally.
r1-p002silent prediction offTry/finally reassignmentAssignment inside a try block where finally reassigns the variable would lose the finally's effect on the returned value.
r1-p003fired, no fixGenerator iterator consumptionGenerators vs lists, iterators consumed once, lazy vs eager evaluation
r1-p004silent prediction offMutable default argument aliasingMutable default arguments and aliasing after a rewrite
r1-p005silent prediction offYield in expression changes generator behaviorAssignment where the expression is a yield or yield-from expression would change the generator's behavior if the yield is moved into a return statement.
r1-p006fired, no fixFloat division and roundingint/float/bool coercion, Decimal, division and rounding
r1-p007silent prediction offType hint annotation droppedAssignment to a variable that is annotated with a type comment or type hint would drop the annotation if the assignment is removed, affecting static analysis.
r1-p008invalidMulti-line statement indentation breakAssignment that is the only statement in a block that ends with a return, but the block is part of a multi-line statement (e.g., continuation lines), could break parsing if the fix removes indentation
r2-p001fired, no fixType annotation evaluated at runtime with typing importtype annotations evaluated at runtime, typing-only imports
r2-p002silent prediction offProperty setter invocation lost by direct returnAssignment that includes a delayed evaluation via a property setter would lose the setter invocation if the expression is returned directly.
r2-p003silent prediction offKeyword-only arg default eval oncekeyword-only, positional-only, *args/**kwargs forwarding, defaults evaluated once
r2-p004fired, no fixWalrus in list comprehension alters iterationAssignment with a walrus operator (:=) inside a list comprehension or other comprehension changes the iteration semantics if the variable is used elsewhere in the comprehension.
r2-p005silent prediction offLambda captures var before assignment overwrites itAssignment to a variable that is also read in a lambda or nested function defined later in the same scope would break closure capture.
r2-p006silent prediction offYield moved to return breaks generatorAssignment where the expression is a yield or yield-from expression would change the generator's behavior if the yield is moved into a return statement.
r2-p007silent prediction offException in expression affects finallyexceptions raised inside the rewritten code, finally/else clauses, exception chaining
r2-p008fired, no fixShadowed built-in len redefined latershadowed builtins and names redefined later in the module

Sources

r1-p001 · Conditional block skip
1def f(b):
2 if b:
3 x = 1 / 0
4 else:
5 x = 42
6 return x
7print(f(True))
8print(f(False))
r1-p002 · Try/finally reassignment
1def f():
2 try:
3 x = 1
4 finally:
5 x = 2
6 return x
7print(f())
2
r1-p003 · Generator iterator consumption
1def f():
2 gen = (i for i in [1])
3 x = list(gen)
4 return x
5print(f())
6print(f())
[1]
[1]
r1-p004 · Mutable default argument aliasing
1def f(a=[]):
2 x = a
3 x.append(1)
4 return x
5print(f())
6print(f())
[1]
[1, 1]
r1-p005 · Yield in expression changes generator behavior
1def f():
2 x = (yield 1)
3 return x
4g = f()
5print(next(g))
6try:
7 g.send(2)
8except StopIteration as e:
9 print(e.value)
1
2
r1-p006 · Float division and rounding
1def f():
2 x = 1 / 3 * 3
3 return x
4print(repr(f()))
1.0
r1-p007 · Type hint annotation dropped
1def f():
2 x: int = 1
3 return x
4print(f())
5print(f.__annotations__)
1
{}
r1-p008 · Multi-line statement indentation break (generated program does not parse: Traceback (most recent call last):)
1def f():\n if True:\n x = 1 \\
2 + 1\n return x\nprint(f())
r2-p001 · Type annotation evaluated at runtime with typing import
1from typing import List
2
3def f() -> List[int]:
4 x = []
5 return x
r2-p002 · Property setter invocation lost by direct return
1class C:
2 @property
3 def value(self):
4 return self._v
5 @value.setter
6 def value(self, v):
7 self._v = v * 2
8
9def f():
10 c = C()
11 c.value = 5
12 return c.value
r2-p003 · Keyword-only arg default eval once
1default = []
2def f(*, x=default):
3 x.append(1)
4 return x
5print(f())
6print(f())
[1]
[1, 1]
r2-p004 · Walrus in list comprehension alters iteration
1def f():
2 data = [1, 2, 3]
3 result = [(x := i) * 2 for i in data if x > 0]
4 return result
5print(f())
r2-p005 · Lambda captures var before assignment overwrites it
1def f():
2 x = 10
3 g = lambda: x
4 x = 20
5 return g()
6print(f())
20
r2-p006 · Yield moved to return breaks generator
1def f():
2 x = (yield 1)
3 return x
4print(list(f()))
[1]
r2-p007 · Exception in expression affects finally
1def f():
2 try:
3 x = 1 / 0
4 except ZeroDivisionError as e:
5 print('caught:', e)
6 raise
7 return x
8try:
9 f()
10except ZeroDivisionError as e:
11 print('re-raised:', e)
caught: division by zero
re-raised: division by zero
r2-p008 · Shadowed built-in len redefined later
1def f():
2 len = lambda x: 42
3 x = len([1, 2, 3])
4 return x
5print(f())
6print(len([1, 2, 3]))
42
3