Skip to content

match does not infer never with None followed by Literal #21780

Description

@haroldbruintjes

The following match statement fails to properly infer a Never type for assert_never:

from typing import assert_never

def f(x: int | tuple[int, int] | None) -> float | None:
    match x:
        case None:
            return None
        case int(0):
            return 0.0
        case int(bits):
            return bits / 8.0
        case int(bits), int(seconds):
            return bits / 8.0 / seconds
        case _:
            assert_never(x)

For some reason, the ordering of the match arms is highly specific (though the ordering between int(0) and int(bits) cannot be changed), and only this specific one triggers the error. reveal_type shows every individual arm properly infers the right type, it seems, except case _.

To Reproduce

See https://mypy-play.net/?gist=8125a531dbf7017902af9240aa22b009 .

Expected Behavior

Mypy reports no issues for the match statement.

Actual Behavior

mypy reports main.py:19: error: Argument 1 to "assert_never" has incompatible type "object"; expected "Never" [arg-type], appararently unable to properly infer the "remaining" type of the last match arm (which should be Never).

Your Environment

Used mypy from the playground (though I first noticed it in our dev environment with mypy 2.1.0 and python 3.14).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions