python / python/mypy

Unexpected Errors When Using Invariant, Covariant, and Contravariant Type Variables in Protocols for `__class_getitem__`

Offen
#17,733 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

bug
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

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:

  1. Invariant Type Variable: Using an invariant type variable T results in an error because the protocol expects a covariant type variable in this context.
  2. 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.
  3. Contravariant Type Variable: Using a contravariant type variable T_contra also 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.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Reproduziere die drei Protokolldefinitionen aus dem Issue mit Python 3.12.2 und mypy 1.11.2 und vergleiche anschließend die gemeldeten Varianzdiagnosen. Überprüfe mypys Behandlung der Protokollvarianz und die vorhandenen Tests für class_getitem; abgeschlossen ist die Aufgabe, wenn das beabsichtigte gültige Varianzverhalten festgestellt und eine Regressionstestabdeckung für diese Fälle hinzugefügt wurde.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.