Skip to content

Type is not inferred in match statement #18833

Open
@unexcellent

Description

@unexcellent

Bug Report

When doing pattern matching with types, the match statement might be more readable than multiple if statements

match (a is None, b is None):
    case (True, True):
        ...
    case (True, False):
        ...
    case (False, True):
        ...
    case (False, False):
        ...

instead of

if a is None and b is None:
    ...
if a is None and b is not None:
    ...
if a is not None and b is None:
    ...
if a is not None and b is not None:
    ...

However, mypy is not able to infer types from the match statements like it is from if statements.

To Reproduce

Infer types using a match statement:

def example_with_match(a: str | None, b: str | None) -> str:
    match (a is None, b is None):
        case (True, True):
            return ""
        case (True, False):
            return b
        case (False, True):
            return a
        case (False, False):
            return a + b

    raise RuntimeError  # unreachable

Gist

Expected Behavior

Like in the equivalent using if statements (there are no mypy errors)

def example_with_if(a: str | None, b: str | None) -> str:
    if a is None and b is None:
        return ""
    if a is None and b is not None:
        return b
    if a is not None and b is None:
        return a
    if a is not None and b is not None:
        return a + b

    raise RuntimeError  # unreachable

Gist

Actual Behavior

whatever.py:6: error: Incompatible return value type (got "str | None", expected "str")  [return-value]
whatever.py:8: error: Incompatible return value type (got "str | None", expected "str")  [return-value]
whatever.py:10: error: Unsupported operand types for + ("str" and "None")  [operator]
whatever.py:10: error: Unsupported left operand type for + ("None")  [operator]

Your Environment

  • Mypy version used: 1.15.0
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files):
[tool.mypy]
check_untyped_defs = true
no_implicit_optional = true
show_error_codes = true
warn_redundant_casts = true
warn_unreachable = true
python_version = "3.12"
ignore_missing_imports = true
  • Python version used: 3.12.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-match-statementPython 3.10's match statement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions