[ty] Fix rare panic with highly cyclic TypeVar definitions (#21059)
Some checks are pending
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (${{ github.repository == 'astral-sh/ruff' && 'depot-windows-2022-16' || 'windows-latest' }}) (push) Blocked by required conditions
CI / cargo test (macos-latest) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / ty completion evaluation (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks walltime (medium|multithreaded) (push) Blocked by required conditions
CI / benchmarks walltime (small|large) (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions

This commit is contained in:
Micha Reiser 2025-10-24 18:30:54 +02:00 committed by GitHub
parent eb8c0ad87c
commit adbf05802a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 318 additions and 71 deletions

View file

@ -0,0 +1,149 @@
# Iteration count mismatch for highly cyclic type vars
Regression test for <https://github.com/astral-sh/ty/issues/1377>.
The code is an excerpt from <https://github.com/Gobot1234/steam.py> that is minimal enough to
trigger the iteration count mismatch bug in Salsa.
<!-- expect-panic: execute: too many cycle iterations -->
```toml
[environment]
extra-paths= ["/packages"]
```
`main.py`:
```py
from __future__ import annotations
from typing import TypeAlias
from steam.message import Message
TestAlias: TypeAlias = tuple[Message]
```
`/packages/steam/__init__.py`:
```py
```
`/packages/steam/abc.py`:
```py
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Generic, Protocol
from typing_extensions import TypeVar
if TYPE_CHECKING:
from .clan import Clan
from .group import Group
UserT = TypeVar("UserT", covariant=True)
MessageT = TypeVar("MessageT", bound="Message", default="Message", covariant=True)
class Messageable(Protocol[MessageT]): ...
ClanT = TypeVar("ClanT", bound="Clan | None", default="Clan | None", covariant=True)
GroupT = TypeVar("GroupT", bound="Group | None", default="Group | None", covariant=True)
class Channel(Messageable[MessageT], Generic[MessageT, ClanT, GroupT]): ...
ChannelT = TypeVar("ChannelT", bound=Channel, default=Channel, covariant=True)
class Message(Generic[UserT, ChannelT]): ...
```
`/packages/steam/chat.py`:
```py
from __future__ import annotations
from typing import TYPE_CHECKING, Generic, TypeAlias
from typing_extensions import Self, TypeVar
from .abc import Channel, ClanT, GroupT, Message
if TYPE_CHECKING:
from .clan import Clan
from .message import ClanMessage, GroupMessage
ChatT = TypeVar("ChatT", bound="Chat", default="Chat", covariant=True)
MemberT = TypeVar("MemberT", covariant=True)
AuthorT = TypeVar("AuthorT", covariant=True)
class ChatMessage(Message[AuthorT, ChatT], Generic[AuthorT, MemberT, ChatT]): ...
ChatMessageT = TypeVar("ChatMessageT", bound="GroupMessage | ClanMessage", default="GroupMessage | ClanMessage", covariant=True)
class Chat(Channel[ChatMessageT, ClanT, GroupT]): ...
ChatGroupTypeT = TypeVar("ChatGroupTypeT", covariant=True)
class ChatGroup(Generic[MemberT, ChatT, ChatGroupTypeT]): ...
```
`/packages/steam/channel.py`:
```py
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from .chat import Chat
if TYPE_CHECKING:
from .clan import Clan
class ClanChannel(Chat["Clan", None]): ...
```
`/packages/steam/clan.py`:
```py
from __future__ import annotations
from typing import TYPE_CHECKING, TypeVar
from typing_extensions import Self
from .chat import ChatGroup
class Clan(ChatGroup[str], str): ...
```
`/packages/steam/group.py`:
```py
from __future__ import annotations
from .chat import ChatGroup
class Group(ChatGroup[str]): ...
```
`/packages/steam/message.py`:
```py
from __future__ import annotations
from typing import TYPE_CHECKING
from typing_extensions import TypeVar
from .abc import BaseUser, Message
from .chat import ChatMessage
if TYPE_CHECKING:
from .channel import ClanChannel
class GroupMessage(ChatMessage["str"]): ...
class ClanMessage(ChatMessage["ClanChannel"]): ...
```