[1.20 regression] Type narrowing is order sensitive in match-case statement with narrowed enum type
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