python / python/mypy

Misleading error message with `dict.get` like method. (polymorphic function with conflicting context)

Offen
#20,576 4 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

Consider this example that emulates dict.get: (https://mypy-play.net/?mypy=latest&python=3.12)

from typing import Any, reveal_type

class Map[K, V]:
    def set(self, key: K, value: V) -> None: ...
    def get[T](self, key: Any, default: T, /) -> V | T: ...

d_any: Map[str, Any] = Map()

reveal_type(d_any.get("key", None))  # Any | None  ✅️

result: str = reveal_type(d_any.get("key", None))  # Any | str ❌️
# error: Argument 2 to "get" of "Map" has incompatible type "None"; expected "str" 

mypys error message is misleading. None is a perfectly reasonable argument for the default value of d_any.get. The problem is that the return type Any | None is not assignable to str. It would make more sense if either:

  1. mypy reports that Any | None cannot be assigned to str.
    (e.g. by a two step approach: first try to solve with context and if that fails, use the return type that is inferred from the arguments alone)[^1]
  2. mypy reports that it cannot find a solution for the type variable T.
    (e.g. single step that considers both constraints from arguments and context)

[^1]: In certain special cases like tuple/list/set/dict-comprehensions, the current behavior that inverts the priority seems fine

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

Beginne damit, das Beispiel im verlinkten mypy playground zu reproduzieren, und vergleiche die Diagnose mit den beiden vorgeschlagenen Ergebnissen. Verfolge mypy's generische Typinferenz und sein Verhalten bei der kontextuellen Typisierung für den polymorphen get-Aufruf. Als abgeschlossen gilt die Aufgabe, wenn die Diagnose nicht mehr fälschlicherweise None die Schuld gibt und ein Regressionstest dieses Beispiel abdeckt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

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

Neue Issues direkt in Ihr Postfach

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