-
Notifications
You must be signed in to change notification settings - Fork 219
Description
from ty_extensions import is_equivalent_to, is_subtype_of, static_assert
from typing import Generator
class A: ...
class B: ...
static_assert(not is_equivalent_to(Generator[None, None, A], Generator[None, None, B]))
static_assert(not is_subtype_of(Generator[None, None, A], Generator[None, None, B]))
static_assert(not is_subtype_of(Generator[None, None, B], Generator[None, None, A]))The assertions here should pass. They do pass on Python 3.13+, but fail on Python 3.12 or older.
The reason is that Generator is a protocol, and its third type parameter (ReturnT_co) is unused in its interface (as defined in typeshed) in Python earlier than 3.13.
As far as the definition given in typeshed, I think ty's conclusion here is correct. But generators are rather special, specifically in that their "return" value also gets wrapped into the StopIteration exception that ends their iteration (even on 3.12 and earlier), but this is not visible in their type system interface. Thus their ReturnT_co always matters (quite a lot -- this is the key mechanism by which async/await works), but typeshed's definition doesn't make that explicit.
I think we will probably need to special-case this type somehow to understand that its ReturnT_co always matters, even on older Python versions.