Incorrect type inferencing when parameterizing with Self-like type variable involving `__ge__`

Ouverte
#13,864 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
28/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
À l'abandon
Stack technique
python
Domaine
devtools

Piste de recherche

Commencez par exécuter le reproducer fourni avec la version actuelle de mypy et tracer l’inférence pour foo, en particulier le paramètre SupportsComparison de type Self et les méthodes ge. Localisez les tests d’inférence de types pertinents ou ajoutez un test de régression pour l’exemple ; le travail est terminé lorsque reveal_type signale tuple[float, float] plutôt que tuple[Fraction, float].

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

bug

Found a very strange bug involving self-like type variables while using __ge__ and similar methods. The following example defines:

  • a parameterized protocol SupportsComparison which takes Self as its first parameter and the type being compared to with its other parameter,
  • a protocol SupportsRadd which allows type-hinting type(t + supports_radd) == type(t),
  • a function foo should then accept foo(x, y, z) where x supports comparison with y and z supports radd with x and returns (x, y).

In the example, foo(float, float, Fraction) -> tuple[float, float] is the expected result, since:

  • float supports comparison with float and self should be float, meaning x: SupportsComparison[float, float],
  • Fraction supports radd with float, meaning z: SupportsRadd[float].

However, the result given by reveal_type(...) gives tuple[Fraction, float]. How is this the case?

from typing import Any, Protocol, TypeVar

T = TypeVar("T")
T_con = TypeVar("T_con", contravariant=True)

Self = TypeVar("Self", bound="SupportsComparison[Any, Any]", covariant=True)


class SupportsComparison(Protocol[Self, T_con]):

    def __ge__(self: Self, other: T_con) -> bool: ...
    def __gt__(self: Self, other: T_con) -> bool: ...
    def __le__(self: Self, other: T_con) -> bool: ...
    def __lt__(self: Self, other: T_con) -> bool: ...


class SupportsRadd(Protocol[T]):

    def __radd__(self, other: T) -> T: ...


X = TypeVar("X", bound=SupportsComparison[Any, Any])
Y = TypeVar("Y")
Z = TypeVar("Z", bound=SupportsRadd[Any])

def foo(
    x: SupportsComparison[X, Y],
    y: Y,
    z: SupportsRadd[X],
) -> tuple[X, Y]:
    return (x, y)

from fractions import Fraction

reveal_type(foo(float(), float(), Fraction()))  # Revealed type is "Tuple[fractions.Fraction*, builtins.float*]"
  • Mypy version: 0.942.
  • Python version used: 3.10.0.
Langage dominant
Python
Étoiles
20.6k
Forks
3.3k
Merge moyen
1 j 18 h
PR mergées (30 j)
54

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de python/mypy

Toutes les issues de python/mypy

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.