Bug Report
Under specific circumstances, changing the order of case-statements in a match-statement influences mypy's type narrowing, leading to flaky assert_never errors.
Specifically, this happens you narrow enum values to specific enum values using Literal and combine that narrowed type with other types in a union.
(I've not done an exhaustive search, but I've only seen this with Literal[SomeEnum.SPECIFIC_VALUE].)
This bug does not occur with mypy==1.19
I've tried to reproduce this bug with Mypy 1.19, but it only occurs with Mypy 1.20. (We ran into this after upgrading Mypy.)
To Reproduce
In the script below, the only different between the dummy_class_then_enum and enum_then_dummy_class is the order of the case-statements within the match statement.
In both instances, all possible value types are handled, but mypy will throw an error on the assert_never in the enum_then_dummy_class function.
import enum
from typing import Literal, assert_never
class DummyClass:
"""A dummy class."""
class MyEnum(enum.StrEnum):
"""A dummy enum class."""
RELEVANT = enum.auto()
IGNORED = enum.auto()
type MyUnionType = DummyClass | Literal[MyEnum.RELEVANT]
def dummy_class_then_enum(arg: MyUnionType) -> str:
match arg:
case DummyClass():
return "dummy class"
case MyEnum.RELEVANT:
return "relevant"
case _ as unreachable:
assert_never(unreachable)
def enum_then_dummy_class(arg: MyUnionType) -> str:
match arg:
case MyEnum.RELEVANT:
return "relevant"
case DummyClass():
return "dummy class"
case _ as unreachable:
assert_never(unreachable)
Expected Behavior
Mypy reports no errors (or errors for both functions).
Actual Behavior
We only get an error for the second function, not the first.
(mypy-demo) sebastiaan@python MypyDemo % mypy bug_demo.py
bug_demo.py:36: error: Argument 1 to "assert_never" has incompatible type "Literal[MyEnum.RELEVANT]"; expected "Never" [arg-type]
Found 1 error in 1 file (checked 1 source file)
Your Environment
- Mypy version used:
1.20
- Mypy command-line flags: None
- Mypy configuration options from
mypy.ini (and other config files): None
- Python version used:
3.14.3
Bug Report
Under specific circumstances, changing the order of
case-statements in amatch-statement influences mypy's type narrowing, leading to flakyassert_nevererrors.Specifically, this happens you narrow enum values to specific enum values using
Literaland combine that narrowed type with other types in a union.(I've not done an exhaustive search, but I've only seen this with
Literal[SomeEnum.SPECIFIC_VALUE].)This bug does not occur with mypy==1.19
I've tried to reproduce this bug with Mypy 1.19, but it only occurs with Mypy 1.20. (We ran into this after upgrading Mypy.)
To Reproduce
In the script below, the only different between the
dummy_class_then_enumandenum_then_dummy_classis the order of thecase-statements within thematchstatement.In both instances, all possible value types are handled, but
mypywill throw an error on theassert_neverin theenum_then_dummy_classfunction.Expected Behavior
Mypy reports no errors (or errors for both functions).
Actual Behavior
We only get an error for the second function, not the first.
Your Environment
1.20mypy.ini(and other config files): None3.14.3