erroneous type mismatch with `Union` and `Literal` (false positive)
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 20.6k
- Forks
- 3.3k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Bug Report
Mypy does not sufficiently simplify Unions and Literals before some type checks (the reproduction case uses assert_type(), but assignments and calls will also trigger the issue). The result is false positive errors.
To Reproduce
from __future__ import annotations
from enum import (
Enum,
auto,
)
from typing import (
Literal,
Union,
)
from typing_extensions import (
assert_type,
reveal_type,
)
class Color(Enum):
RED = auto()
GREEN = auto()
BLUE = auto()
RedKwds = Literal['RED', 'R']
GreenKwds = Literal['GREEN', 'G']
BlueKwds = Literal['BLUE', 'B']
ColorKwds = Union[RedKwds, GreenKwds, BlueKwds]
RedSpec = Union[Literal[Color.RED], RedKwds]
GreenSpec = Union[Literal[Color.GREEN], GreenKwds]
BlueSpec = Union[Literal[Color.BLUE], BlueKwds]
ColorSpec = Union[Color, ColorKwds] # ⎱ these are entirely
RGBSpec = Union[RedSpec, GreenSpec, BlueSpec] # ⎰ equivalent types
rgb_spec: RGBSpec
assert_type(rgb_spec, ColorSpec) # fails; should be silent # L34
# Expression is of type...
# Union[
# Union[Literal[Color.RED], Literal['RED', 'R']],
# Union[Literal[Color.GREEN], Literal['GREEN', 'G']],
# Union[Literal[Color.BLUE], Literal['BLUE', 'B']]
# ]
# ... not ...
# Union[
# Color,
# Union[
# Literal['RED', 'R'],
# Literal['GREEN', 'G'],
# Literal['BLUE', 'B']
# ]
# ]
reveal_type(rgb_spec) # L50
# Union[
# Literal[Color.RED], Literal['RED'], Literal['R'],
# Literal[Color.GREEN], Literal['GREEN'], Literal['G'],
# Literal[Color.BLUE], Literal['BLUE'], Literal['B']
# ]
# "shaking" the variable (where "shaking" is clearly a no-op) causes
# things to work as expected:
rgb_spec_shaken = (
rgb_spec
if isinstance(rgb_spec, Color) else
rgb_spec
)
assert_type(rgb_spec_shaken, ColorSpec) # passes!
reveal_type(rgb_spec_shaken) # L66
# Union[
# Color,
# Literal['RED'], Literal['R'],
# Literal['GREEN'], Literal['G'],
# Literal['BLUE'], Literal['B']
# ]
Expected Behavior
The types are provably equivalent; no error should be raised.
Actual Behavior
Mypy does not sufficiently simplify the types, resulting in an erroneous "mismatch".
Your Environment
- Mypy version used: 1.9.0, master 2024-04-22
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini(and other config files): none - Python version used: 3.8, 3.12
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne damit, die mypy-play-Reproduktion des Issues mit den gezeigten assert_type()- und reveal_type()-Fällen auszuführen, insbesondere die Zeilen 34 und 50, und untersuche dann die an diesen Prüfungen beteiligten Pfade zur Typvereinfachung und -kompatibilität. Erledigt ist die Aufgabe, wenn äquivalente Union- und Literal-Typen nicht mehr zu einer Nichtübereinstimmung führen und der angezeigte aufgelöste Typ angemessen vereinfacht ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- tooling
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 45/100