ty icon indicating copy to clipboard operation
ty copied to clipboard

ty check takes very long time with generic protocols

Open n-gao opened this issue 2 months ago • 1 comments

Summary

This is a follow up to #1874.

I cannot pin point exactly what causes this issue but the following code takes a very long time to check

from __future__ import annotations
from typing import Any, Callable, Protocol


class M[R](Protocol):
    def __call__(self, r: R, /) -> R: ...


class A[S, R](Protocol):
    def get(self, s: S) -> R: ...
    def set(self, s: S, r: R) -> S: ...
    def bind(self, s: S) -> B[S, R]: ...
    def merge[R2](self, other: A[S, R2]) -> A[S, tuple[R, R2]]: ...
    def nest[U](self, inner: A[R, U]) -> A[S, U]: ...
    def at(self, idx: Any) -> A[S, R]: ...
    def apply(self, s: S, modifier: M[R]) -> S: ...


class B[S, R](Protocol):
    def focus[R2](self, where: Callable[[R], R2]) -> B[S, R2]: ...
    def get(self, s: S) -> R: ...
    def set(self, s: S, r: R) -> S: ...
    def apply(self, s: S, modifier: M[R]) -> S: ...
    def at(self, idx: Any) -> B[S, R]: ...
    def merge[R2](self, other: A[S, R2]) -> B[S, tuple[R, R2]]: ...


class Impl[S, R](A[S, R]):
    def apply(self, s: S, modifier: M[R]) -> S:
        return self.set(s, modifier(self.get(s)))

Output:

time uv run ty check ./test.py
All checks passed!
uv run ty check ./test.py  3.06s user 0.19s system 97% cpu 3.349 total

Removing the apply function from the definition of Impl results in a huge speedup:

time uv run ty check ./test.py
All checks passed!
uv run ty check ./test.py  0.02s user 0.02s system 39% cpu 0.122 total

For our whole codebase this slowdown makes ty unusable as it freezes. This was a minimal example where I could narrow the slower type checking times.

Version

ty 0.0.1-alpha.35 (3188a56be 2025-12-16)

n-gao avatar Dec 16 '25 11:12 n-gao

Thanks for the report and minimized example! We'll take a look.

carljm avatar Dec 16 '25 16:12 carljm