erroneous type mismatch with `Union` and `Literal` (false positive)
オープン
まだ誰も着手していません。
bug
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- PR マージ指標
- PR 指標を取得中
説明
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
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、示されている assert_type() と reveal_type() のケースを使って issue の mypy-play 再現を実行します。特に 34 行目と 50 行目を確認し、その後、それらのチェックに関係する型の単純化および互換性のパスを調べます。完了条件は、同値な Union 型と Literal 型で不一致が発生しなくなり、表示される revealed type が適切に単純化されることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- tooling
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100