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.