-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Bug Report
Mypy does not exclude types from earlier match cases in subsequent cases. This makes it difficult to work with values that could match multiple cases.
I'm specifically running into this when trying to handle types from the OpenAI and Anthropic Python SDKs. The type annotations in those libraries frequently have patterns like content: Union[str, Iterable[ContentArrayOfContentPart], None]. Applying a match/case statement to the content causes issues in the case Iterable(): case, because Mypy thinks that the value could still be a string (even though that was handled in a previous case).
To Reproduce
import random
from collections.abc import Iterable
from typing import assert_never
x: str | list[int]
if random.random() < 0.5:
x = "a"
else:
x = [1, 2, 3]
match x:
case str():
reveal_type(x)
case Iterable():
reveal_type(x)
case _:
assert_never(x)Expected Behavior
I would expect Mypy to show a revealed type of only builtins.list[builtins.int] for x on line 17, like:
main.py:15: note: Revealed type is "builtins.str"
main.py:17: note: Revealed type is "builtins.list[builtins.int]"
Success: no issues found in 1 source file
Actual Behavior
Even though a string would never make it to the second case, x on line 17 is still considered to possibly be a string:
main.py:15: note: Revealed type is "builtins.str"
main.py:17: note: Revealed type is "builtins.str | builtins.list[builtins.int]"
Success: no issues found in 1 source file
Your Environment
- Mypy version used: 1.18.2
- Mypy command-line flags: N/A
- Mypy configuration options from
mypy.ini(and other config files): N/A - Python version used: 3.12