python / python/mypy

`Iterable[Any]` incorrectly matches `Iterable[Never]` overload, inferring `Never` instead of the element type

Offen
#21,317 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

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

Beschreibung

Bug Report

When a class (e.g., Box in our example below) has two __init__ overloads — one taking Iterable[Never] (binding self to Box[Never]) and one taking Iterable[_T] (binding self to Box[_T]) — passing a value whose iteration type is Any incorrectly resolves to the Iterable[Never] overload, yielding Box[Never] instead of Box[_T].

To Reproduce

Gist URL: https://gist.github.com/mypy-play/d326ca961e53d4c9d085cfda05f3e455
Playground URL: https://mypy-play.net/?gist=d326ca961e53d4c9d085cfda05f3e455

# any_never_bug.py
from enum import IntEnum
from typing import Generic, Iterable, Never, TypeVar, overload, reveal_type

_T = TypeVar("_T")


class Box(Generic[_T]):
    @overload
    def __init__(self: "Box[Never]", val: Iterable[Never]) -> None: ...
    @overload
    def __init__(self: "Box[_T]", val: Iterable[_T]) -> None: ...
    def __init__(self, val: object) -> None: ...


class Color(IntEnum):
    RED = 1
    GREEN = 2


reveal_type(Box(Color))  # Expected: Box[Color], mypy gives: Box[Never]
% mypy --config-file /dev/null any_never_bug.py
/dev/null: No [mypy] section in config file
any_never_bug.py:21: note: Revealed type is "any_never_bug.Box[Never]"
Success: no issues found in 1 source file

Expected Behavior

Expected: Box[Color]
Actual: Box[Never]

Notes:

My best guess on root cause is that EnumMeta.__iter__ is typed in typeshed as returning Iterator[Any], so Color (the class) is seen as Iterable[Any]. I'm guessing that since Any is consistent with Never, mypy selects the Iterable[Never] overload rather than the more general Iterable[_T] one. However, Iterable[Any] should probably not be considered assignable to Iterable[Never]. I'm pretty sure Never is the bottom type and nothing except Never itself should be a subtype of it. Pyright and Pyrefly both correctly infer Box[Color] for this case.

Your Environment

  • Mypy version used: mypy 1.20.2 (compiled: yes)
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: Python 3.11.15

Ref: astral-sh/ty#3330

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

Starte zunächst den Reproduzierer any_never_bug.py mit mypy --config-file /dev/null und bestätige den angezeigten Typ. Verfolge die Auflösung der Überladungen für Iterable[Any] anhand der Signaturen Iterable[Never] und Iterable[_T]. Überprüfe anschließend, dass das Ergebnis Box[Color] ist, ohne das gezeigte Überladungsverhalten zu verschlechtern.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers, devtools
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Ruhig
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
45/100

Neue Issues direkt in Ihr Postfach

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