python / python/mypy

Unexpected Overloading overlap if String Literal is used within Sequence/Iterable/Collection

Offen
#15,035 6 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

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

Beschreibung

Bug Report

If I have a function that accepts a String Literal and Sequence of String Literal and want to overload this function for these two cases, mypy always returns:

Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]

from typing import overload, Literal

@overload
def over(bar: Literal["bar"]) -> int:  # Overloaded function signatures 1 and 2 overlap with incompatible return types  [misc]
    ...

@overload
def over(bar: Sequence[Literal["foo"]]) -> str:
    ...   

def over(bar: Literal["bar"]|Sequence[Literal["foo"]]) -> str|int:
    if bar == "bar":
        return 0
    return ", ".join(bar)
    

To Reproduce
https://mypy-play.net/?mypy=latest&python=3.11&gist=d28d528c0765dc0a4a004c360a4008a4

Expected Behavior

No error, as if we would use a list instead:

@overload
def load(bar: Literal["bar"]) -> int:
    ...

@overload
def load(bar: list[Literal["foo"]]) -> str:
    ...   

def load(bar: Literal["bar"]|list[Literal["foo"]]) -> str|int:
    if bar == "bar":
        return 0
    return ", ".join(bar)

Actual Behavior
Mypy returns:

Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]

Your Environment

MyPy playground....

  • Mypy version used: 1.20
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: tested with 3.10 and 3.11

Note
I am aware that a str is also a Sequence[str]. But as we using literals here, this shouldn't matter.

This is only an issue for mypy if used with overloads, it works correctly if simply used within a function

# Simple example, that if we use Sequences and Literals, mypy
# can determine stuff correctly
def foo(bar: Literal["bar"]|Sequence[Literal["foo"]]) -> None:
    return None
    
    
foo("bar")  # okay
foo(["foo"]) # okay
foo("foo") # not okay - as expected
foo(["bar"]) # not okay - as expected

Note that pyright does detect the overloads correctly (kind of).

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 die verlinkte mypy-play-Reproduktion und vergleiche die Overload-Beispiele mit Sequence, Iterable, Collection und list mit den abschließenden Prüfungen der Funktionsaufrufe. Verfolge die beteiligte Overload-Kompatibilität und die Literal-Behandlung im gemeldeten Diagnosefehler. Als erledigt gilt die Aufgabe, wenn die gültigen String-Literal- und Sequenz-Overloads keinen Fehler wegen inkompatibler Überschneidung mehr erzeugen, während die ungültigen Aufrufe weiterhin abgelehnt werden.

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
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

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