mypy icon indicating copy to clipboard operation
mypy copied to clipboard

An empty generic class is covariant even though the doc says "all user-defined generic classes invariant by default"

Open hyperkai opened this issue 1 month ago • 3 comments

*Memo:

  • mypy --strict test.py
  • mypy 1.19.0
  • Python 3.14.0
  • Windows 11

Invariance vs covariance says mypy considers all user-defined generic classes invariant by default as shown below:

Most mutable generic collections are invariant, and mypy considers all user-defined generic classes invariant by default (see Variance of generic types for motivation). This could lead to some unexpected errors when combined with type inference. For example:

But an empty generic class is covariant against what the doc says as shown below:

class A: ...
class B(A): ...
class C(B): ...

class MyCls[T]: ...

mycls1: MyCls[A] = MyCls[B]() # No error
mycls2: MyCls[B] = MyCls[B]() # No error
mycls3: MyCls[C] = MyCls[B]() # Error

hyperkai avatar Dec 05 '25 22:12 hyperkai

Yes the docs are wrong here. What's true is that under the old syntax T = TypeVar("T"), a TypeVar is invariant by default. But under the new PEP 695 syntax, classes are covariant by default if they don't use the TypeVar.

JelleZijlstra avatar Dec 06 '25 01:12 JelleZijlstra

@JelleZijlstra Hi! I'd like to work on this issue , may take it ?

khanak0509 avatar Dec 07 '25 15:12 khanak0509

@khanak0509 there is no process for claiming issues on mypy, so anyone may work on it — including you :)

In this case, the change itself will be easy, but you will probably have to spend a significant amount of time figuring out if your new explanation is entirely correct, as the variance rules can be tricky to phrase in an exactly correct manner. A common problem is that people propose changes without really understanding these situations (I am no exception), inevitably wasting more time in the review process; so, I recommend trying to understand it completely before submitting a PR. Just a tip.

wyattscarpenter avatar Dec 07 '25 23:12 wyattscarpenter