Skip to content

mypy's narrowing for match statements sometimes fails when the subject of the match is a function call #12998

Closed
@zenbot

Description

@zenbot

Bug Report

mypy's narrowing for match statements sometimes fails when the subject of the match is a function call.

To Reproduce

from typing_extensions import assert_never

def fn() -> int | None:
    ...

match fn(): 
    case int():
        pass
    case None:
        pass
    case _ as unreachable:
        assert_never(unreachable)

Expected Behavior

The code above should pass a type check because case statements handle all possible return values of fn().

Actual Behavior

$ mypy --strict bad.py
bad.py:12: error: Argument 1 to "assert_never" has incompatible type "Optional[int]"; expected "NoReturn"
Found 1 error in 1 file (checked 1 source file)

Note

Assigning the return value of fn() to a variable and using that variable as the subject of the match does pass type checking:

from typing_extensions import assert_never

def fn() -> int | None:
    ...

rv = fn()

match rv: 
    case int():
        pass
    case None:
        pass
    case _ as unreachable:
        assert_never(unreachable)

Handling all cases within the one case statement also passes type checking:

from typing_extensions import assert_never

def fn() -> int | None:
    ...

match fn(): 
    case int() | None:
        pass
    case _ as unreachable:
        assert_never(unreachable)

mypy's output for both of the above:

$ mypy --strict bad.py
Success: no issues found in 1 source file

Your Environment

  • Mypy version used: mypy 0.961 (compiled: yes)
  • Mypy command-line flags: --strict
  • Python version used: Python 3.10
  • Operating system and version: macOS Monterey 12.3.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-match-statementPython 3.10's match statementtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions