-
Notifications
You must be signed in to change notification settings - Fork 219
Closed
astral-sh/ruff
#22030Labels
performancePotential performance improvementPotential performance improvement
Milestone
Description
Summary
Hi all - thank you so much for this promising new project! I am excited to get our company using ty ASAP. With the beta announcement today, I tried it out on our JUMBO codebase. In doing so, I have identified the below issue:
Included here is a minimal repro from our codebase (reduced as much as possible and business logic filtered out, i realize it looks silly but i figure it demonstrated the issue well):
"""
Minimal reproduction for ty type checker exponential slowdown.
Run with:
TY_MAX_PARALLELISM=1 ty check slow_ty_repro.py
Timings:
4 types: <1s
5 types: <1s
6 types: ~8s
7 types: >60s (hits my timeout)
Example debug logs:
2025-12-17 01:33:38.681798202 DEBUG left implies right left=(M6 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) right=(U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements)
2025-12-17 01:33:38.682086278 DEBUG left and right overlap left=(M6 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) right=(U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) intersection=(M6 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements)
2025-12-17 01:33:38.683285882 DEBUG left implies right left=(M3 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) right=(U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements)
2025-12-17 01:33:38.683605638 DEBUG left and right overlap left=(M3 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) right=(U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) intersection=(M3 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements)
2025-12-17 01:33:38.683894444 DEBUG left implies right left=(M3 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) right=(M3 ≤ U_co@apply)
2025-12-17 01:33:38.683919264 DEBUG left and right overlap left=(M3 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements) right=(M3 ≤ U_co@apply) intersection=(M3 ≤ U_co@apply ≤ M1 | M2 | M3 | ... omitted 4 union elements)
"""
from __future__ import annotations
from typing import Callable
from typing import Generic
from typing import TypeVar
from typing import Union
class M1: pass
class M2: pass
class M3: pass
class M4: pass
class M5: pass
class M6: pass
class M7: pass
Msg = Union[M1, M2, M3, M4, M5, M6, M7]
T = TypeVar("T")
U_co = TypeVar("U_co", covariant=True)
class Stream(Generic[T]):
def apply(self, func: Callable[["Stream[T]"], "Stream[U_co]"]) -> "Stream[U_co]":
return func(self)
TMsg = TypeVar("TMsg", bound=Msg)
class Builder(Generic[TMsg]):
def build(self) -> Stream[TMsg]:
stream: Stream[TMsg] = Stream()
stream = stream.apply(self._handler) # i think here is where the issue triggers?
return stream
def _handler(self, stream: Stream[Msg]) -> Stream[Msg]:
return streamthis initially just surfaced as what seemed to be a hang during a repo-wide ty check, but debug logs allowed me to narrow down to this file then I just hacked away until i got something which seemed reasonable to share.
Version
0.0.2
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
performancePotential performance improvementPotential performance improvement