Description
Bug Report
While upgrading from 1.9 to 1.10 we found this regression in exhaustiveness checking. It looks like mypy stops inspecting a match expression once it's found an non-possible member.
To Reproduce
Playground link for below, note it's passing on 1.9.
import enum
from typing import assert_never
class Member(enum.Enum):
a = enum.auto()
b = enum.auto()
c = enum.auto()
def fn(value: Member) -> None:
if value is Member.b:
return
match value:
case (
Member.a
| Member.b
| Member.c
):
# This only reveals Member.a!
reveal_type(value)
...
case no_match:
assert_never(no_match)
Related, removing Member.a
causes the reveal_type()
to be muted!
import enum
from typing import assert_never
class Member(enum.Enum):
b = enum.auto()
c = enum.auto()
def fn(value: Member) -> None:
if value is Member.b:
return
match value:
case (
Member.b
| Member.c
):
# No reveal is printed!
reveal_type(value)
...
case no_match:
assert_never(no_match)
It's probably also worth pointing out that order matters. Inverting order in the match expression to case Member.c | Member.b:
makes the issue go away. I suspect an early return optimization to be at fault! 🕵️
Expected Behavior
This was caused by an already excluded member of the enum. The error message that mypy presents does not make this obvious and the fact that it presents it as an exhaustiveness failure I consider a bug that should be fixed.
The reveal_type()
should contain both members .a
and .c
, there should be no type error.
It should be noted that we were able to work around this by removing the erroneously included member (Member.b
in the minimal reproduction) from the match expression.
Actual Behavior
reveal_type()
contains only .a
, and there is a type error:
repro.py:21: note: Revealed type is "Literal[repro.Member.a]"
repro.py:24: error: Argument 1 to "assert_never" has incompatible type "Literal[Member.c]"; expected "NoReturn" [arg-type]
Found 1 error in 1 file (checked 1 source file)
Your Environment
See playground link.