Skip to content

Enum instance type ignored in match/case statements #13841

Closed

Description

@ianonavy

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"

Playground link

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]"

screenshot of Visual Studio Code showing the problems panel with messages that corroborate the above description

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

  1. intgr commented on Jul 27, 2023

    @intgr
    Contributor

    The reason is that mypy thinks this code is unreachable, and skips typechecking of unreachable code. You can see these warnings when using --warn-unreachable option:

    I think this is surprising and bad default behavior. It even ignores reveal_type() in unreachable code.

  2. dpinol commented on Jul 27, 2024

    @dpinol

    A smilar case

    class MyEnum(Enum):
        RAISE = 1
        ERROR = 2
    
        def level(self) -> int:
            match self:
                case self.RAISE:
                    return 1
                case self.ERROR:
                    return 2

    I get

    kk.py:23: error: Statement is unreachable  [unreachable]
                        return 1
                        ^~~~~~~~
    kk.py:25: error: Statement is unreachable  [unreachable]
                        return 2
                        ^~~~~~~~
    Found 2 errors in 1 file (checked 1 source file)
    

    I can be workarounded doing case MyEnum.RAISE instead of case self.RAISE

  3. added a commit that references this issue on Aug 3, 2025
    9d3a052
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions