python / python/mypy

Interaction between an `enum` alias and `assert_never()` seems to fail

Open
#21,117 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-enum topic-type-narrowing
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

If you have defined an enum with some values and an extra value which is an alias of an already defined one, the completeness-check using assert_never(...) does not work as (I) expected.

To Reproduce

# file mypy_enum_alias.py
import enum

from typing import assert_never

class Version(enum.Enum):
    V1 = enum.auto()
    V2 = enum.auto()
    DEFAULT = V2

def print_version(version: Version) -> None:
    match version:
        case Version.V1:
            print("Version 1")
        case Version.V2:
            print("Version 2")
        case _:
            assert_never(version)

print(*(repr(v) for v in Version))
$ mypy mypy_enum_alias.py

Expected Behavior

Success: no issues found in 1 source file

Actual Behavior

mypy_enum_alias.py:18: error: Argument 1 to "assert_never" has incompatible type "Literal[Version.DEFAULT]"; expected "Never"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: mypy 1.19.1 (compiled: yes)
  • Mypy command-line flags: (none)
  • Mypy configuration options from mypy.ini (and other config files):
    # pyproject.toml
    # ...
    [tool.mypy]
    plugins = [
        "pydantic.mypy"
    ]
    # ...
    
  • Python version used: Python 3.13.9

If you run the script, Python bravely emits only the (two) non-aliased values:

$ python mypy_enum_alias.py
<Version.V1: 1> <Version.V2: 2>

If mypy considers all "names" of an enum, it renders the completeness check useless IMHO.

I could add the following code snippet just before case _: ... as a work-around, but that would just be pathetic:

        case Version.DEFAULT:
            pass

But for the rest I'm quite happy with mypy. A great helper in early bug detection!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the reproducer in mypy_enum_alias.py and run mypy with no command-line flags to confirm the incorrect assert_never diagnostic. Trace how mypy handles enum aliases during match exhaustiveness checking, then add or update coverage so the example reports success without requiring a Version.DEFAULT case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.