Skip to content

Pattern matching: Type narrowing in sequence pattern not applied in guard #15949

@arvidfm

Description

@arvidfm

Bug Report

A variable bound in a sequence pattern, e.g. case [*elems]:, does not get narrowed to Sequence in a guard, even though it's correctly narrowed in the body of the case itself:

match v:
    case [*elems] if len(elems) > 0: pass  # fails

This works:

match v:
    case Sequence() as elems if len(elems) > 0: pass

To Reproduce

https://mypy-play.net/?mypy=master&python=3.11&gist=dfed73f09b13db16d94fb7e03a669c77

from typing import Any

def test(v: Any) -> None:
    match v:
        case [*elems] if len(elems) > 0:  # fails
            print("list:", elems)
            print("length:", len(elems))  # works
        case int() as i if i > 0:  # works
            print("positive:", i)
        case _:
            print("other:", v)

if __name__ == "__main__":
    test([1, 2, 3])
    test(5)
    test(-5)

Expected Behavior

The above code should typecheck successfully

Actual Behavior

$ poetry run mypy .
test.py:5: error: Cannot determine type of "elems"  [has-type]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.5.1
  • Mypy command-line flags: mypy .
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.11

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