Unexpected Errors When Using Invariant, Covariant, and Contravariant Type Variables in Protocols for `__class_getitem__`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
I encountered an issue while defining a protocol with type variables that are invariant, covariant, and contravariant for the __class_getitem__ method. My goal was to create a protocol that supports different variance for the key parameter. I expected that at least one of the variance options (invariant, covariant, or contravariant) would work without errors. However, all three approaches result in type errors:
- Invariant Type Variable: Using an invariant type variable
Tresults in an error because the protocol expects a covariant type variable in this context. - Covariant Type Variable: When using a covariant type variable
T_co, I cannot use it as a parameter for the__class_getitem__method, which expects invariance or contravariance. - Contravariant Type Variable: Using a contravariant type variable
T_contraalso leads to an error since it is expected to be covariant in this context.
I was expecting that at least one of these cases would not raise an error.
To Reproduce
from abc import abstractmethod
from typing import Protocol, Self, TypeVar
T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)
T_contra = TypeVar("T_contra", contravariant=True)
R = TypeVar("R")
R_co = TypeVar("R_co", covariant=True)
R_contra = TypeVar("R_contra", contravariant=True)
class SupportsClassGetItemInvariant(Protocol[T, R_co]):
@classmethod
@abstractmethod
def __class_getitem__(cls: type[Self], key: T, /) -> R_co: ...
class SupportsClassGetItemCovariant(Protocol[T_co, R_co]):
@classmethod
@abstractmethod
def __class_getitem__(cls: type[Self], key: T_co, /) -> R_co: ...
class SupportsClassGetItemContravariant(Protocol[T_contra, R_co]):
@classmethod
@abstractmethod
def __class_getitem__(cls: type[Self], key: T_contra, /) -> R_co: ...
Expected Behavior
I expected that at least one of these variations (invariant, covariant, or contravariant) would work without causing a type error in Mypy, allowing me to use the type variable as the key parameter in the __class_getitem__ method.
Actual Behavior
Mypy raises errors for all three cases, indicating that none of the variance annotations are accepted for the key parameter in the __class_getitem__ method within the protocol.
Your Environment
- Mypy version used:
mypy 1.11.2 - Mypy command-line flags: None
- Mypy configuration options from
mypy.ini: None - Python version used:
Python 3.12.2
I would appreciate any insights or suggestions on how to approach this issue, as I was expecting at least one of these scenarios to work.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the three protocol definitions from the issue with Python 3.12.2 and mypy 1.11.2, then compare the reported variance diagnostics. Review mypy's protocol variance handling and existing tests for class_getitem; done means establishing the intended valid variance behavior and adding regression coverage for these cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100