Repository navigation
Enum instance type ignored in match/case statements #13841
Description
Bug Report
When using an enum instance instead of a class property in a case statement, the type checker appears to ignore type errors inside the case statement.
May be related to #11784, not sure.
To Reproduce
import enum
class FooClass(enum.Enum):
FOO = "FOO"
foo_inst = FooClass.FOO
match foo_inst:
case foo_inst.FOO:
1 + "a"Expected Behavior
I expected a type error on line 11, error: Unsupported operand types for + ("int" and "str"). My reasoning is that in cPython 3.10.7, FooClass.FOO and foo_inst.FOO both refer to the same object with the same id and should therefore have the same type checking behavior.
Actual Behavior
If you run mypy:
Success: no issues found in 1 source file
If you run it with python, you get a runtime TypeError even though the type checker failed to catch it.
The expected behavior occurs if you use the class name instead of the instance name:
import enum
class FooClass(enum.Enum):
FOO = "FOO"
foo_inst = FooClass.FOO
match foo_inst:
case FooClass.FOO:
1 + "a"Your Environment
- Mypy version used: 0.982
- Mypy command-line flags: none; same issue with
--strict - Mypy configuration options from
mypy.ini(and other config files): none - Python version used: 3.10.7
More Details
More detailed investigation here
I tried to reveal_type to debug, and I got different values depending on the environment. With the mypy CLI against the following example and mypy Playground, I get the following:
import enum
class FooClass(enum.Enum):
FOO = "FOO"
foo_inst = FooClass.FOO
match foo_inst:
case FooClass.FOO:
reveal_type(FooClass.FOO)
reveal_type(foo_inst)
reveal_type(foo_inst.FOO)
1 + "a"main.py:11: note: Revealed type is "Literal[__main__.FooClass.FOO]?"
main.py:12: note: Revealed type is "__main__.FooClass"
main.py:13: note: Revealed type is "Literal['FOO']?"
main.py:14: error: Unsupported operand types for + ("int" and "str")
Found 1 error in 1 file (checked 1 source file)
If I change line 10 to foo_inst.FOO, I get no revealed types at all: playground link.
Further, Visual Studio Code's bulit-in diagnostics seem to interpret the types for all three expressions as "Literal[FooClass.FOO]"
Curiously, the type checking seems to work when using an IntEnum instead of an Enum: playground link.
import enum
class FooClass(enum.IntEnum):
FOO = 0
foo_inst = FooClass.FOO
match foo_inst:
case foo_inst.FOO:
reveal_type(FooClass.FOO)
reveal_type(foo_inst)
reveal_type(foo_inst.FOO)
1 + "a"main.py:11: note: Revealed type is "Literal[__main__.FooClass.FOO]?"
main.py:12: note: Revealed type is "<nothing>"
main.py:13: error: <nothing> has no attribute "FOO"
main.py:13: note: Revealed type is "Any"
main.py:14: error: Unsupported operand types for + ("int" and "str")
Found 2 errors in 1 file (checked 1 source file)
I also observe the expected behavior with if statements, so I think the issue is particular to the intersection of case and enum instance.

Activity
intgr commentedon Jul 27, 2023
The reason is that mypy thinks this code is unreachable, and skips typechecking of unreachable code. You can see these warnings when using
--warn-unreachableoption:I think this is surprising and bad default behavior. It even ignores
reveal_type()in unreachable code.dpinol commentedon Jul 27, 2024
A smilar case
I get
I can be workarounded doing
case MyEnum.RAISEinstead ofcase self.RAISESupport attribute access on enum members correctly (python#19422)