fixhunt

ruff UP038: tool crashes

tool-crashlabelled unknownprogram-bug · lowrelated
Findings / 2026-10-17T21-20-52-142Z-httm-ruff-UP038 / r2-p008ruff 0.17.18 → 3 lines2026-10-17 21:20 UTC

Hypothesis Nemotron 3 Super predicted to fire did not fire

walrus, comprehensions scoping, late binding in closures and lambdas

Program

before
1fns = []
2for i in range(2):
3 fns.append(lambda: isinstance(x, (int, str)))
after
1(no fix applied)

Output

stdout beforeexit 0
(no stdout)
stdout afternot run
(not run)
fired
0 before · 0 after
runs
each version twice, same file name, no network

Judge Nemotron 3 Ultra advisory program-bug · low

The linter crashed because rule UP038 was removed from the codebase and cannot be selected, not because the rewrite changed program semantics. The oracle observed a tool crash during linting, which is an environment or tooling issue unrelated to the fix's correctness on the source code.

Explanation Nemotron 3 Super unverified

The original loop creates two lambda functions that each capture the current value of x from the enclosing scope when called; since x is unchanged between iterations, both lambdas behave identically. However, if the rewrite attempted to hoist or inline the lambda definition outside the loop—such as defining it once and reusing it—the behavior could differ if x were mutated between calls, because all instances would then share the same closure over a potentially changing x. In this specific case, x is not mutated, so the behavior remains the same, but the rewrite is still unsafe because it assumes x is invariant, which cannot be guaranteed statically. Thus, the transformation may alter semantics in contexts where x varies, making it non‑preserving in general.

Reproduce

file
prog.py (the before program)
minimized program
r2-p008.py
evidence sheet
r2-p008.md
regression fixture
r2-p008.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 UP038 --fix prog.py
python3 prog.py

Upstream search GitHub issues Tavily Nemotron 3 Super + Ultra

UP038 fix · ruff UP038 lambda isinstance · rule UP038 callable expression · UP038 type check pattern

  • related astral-sh/ruff/issues/13051 Existing report concerns outdated documentation for UP038, not a tool crash when the rule is removed.
  • related astral-sh/ruff/issues/7871 Existing report is about UP038 rewriting code to be slower, not about a crash due to the rule being removed.
  • related astral-sh/ruff/issues/18349 Existing report is about a warning for a deprecated rule, not a crash when selecting a removed rule.

Details

program
Walrus, comprehensions scoping, late binding
hazard
walrus, comprehensions scoping, late binding in closures and lambdas
oracle
lint crashed: ruff failed Cause: Rule `UP038` was removed and cannot be selected.
run
2026-10-17T21-20-52-142Z-httm-ruff-UP038
generated program (8 lines) and the fix's diff
1fns = []
2for i in range(2):
3 if (x := i) == 0:
4 fns.append(lambda: isinstance(x, (int, str)))
5 else:
6 fns.append(lambda: isinstance(x, (int, str)))
7print(fns[0]())
8print(fns[1]())
rule documentation given to the models
# non-pep604-isinstance (UP038)

Derived from the **pyupgrade** linter.

Fix is always available.

## Removed
This rule was removed as using [PEP 604] syntax in `isinstance` and `issubclass` calls
isn't recommended practice, and it incorrectly suggests that other typing syntaxes like [PEP 695]
would be supported by `isinstance` and `issubclass`. Using the [PEP 604] syntax
is also slightly slower.

## What it does
Checks for uses of `isinstance` and `issubclass` that take a tuple
of types for comparison.

## Why is this bad?
Since Python 3.10, `isinstance` and `issubclass` can be passed a
`|`-separated union of types, which is consistent
with the union operator introduced in [PEP 604].

Note that this results in slower code. Ignore this rule if the
performance of an `isinstance` or `issubclass` check is a
concern, e.g., in a hot loop.

## Example
```python
isinstance(x, (int, float))
```

Use instead:
```python
isinstance(x, int | float)
```

## Options
- `target-version`

## References
- [Python documentation: `isinstance`](https://docs.python.org/3/library/functions.html#isinstance)
- [Python documentation: `issubclass`](https://docs.python.org/3/library/functions.html#issubclass)

[PEP 604]: https://peps.python.org/pep-0604/
[PEP 695]: https://peps.python.org/pep-0695/