python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.5k stars 2.83k forks source link

Untrue unreachable statements with list pattern matching #16272

Open JanczarKurek opened 1 year ago

JanczarKurek commented 1 year ago

Bug Report When trying to use pattern matching statements that contain list-type matches mypy emits bogus "unreachable" errors.

To Reproduce The following code

    from typing import Any

    def list_len(l: Any):
        match l:
            case []:
                return 0
            case [_]:
                return 1
            case _:
                return "Big number"

generates error

pattern_matching_mypy.py:6: error: Statement is unreachable  [unreachable]

when run with option --warn-unreachable. Curiously it is enough to hint at a possibility of l being a list by doing

    from typing import Any

    def list_len(l: Any | list):
        match l:
            case []:
                return 0
            case [_]:
                return 1
            case _:
                return "Big number"

to make the error disappear.

Expected Behavior Both snippets of code should emit no errors as it is clearly possible to match l if it is a list.

Actual Behavior The following error is generated

pattern_matching_mypy.py:6: error: Statement is unreachable  [unreachable]
pattern_matching_mypy.py:8: error: Statement is unreachable  [unreachable]

My Environment

henryiii commented 2 months ago

I ran into this on 1.11 with:

from typing import Any

ruff: dict[str, Any] = {"src": ["src"], "other": True}
match ruff:
    case {"src": ["src"]}:
        print("got it!")

It's fine with dict[str, object], but the Any makes it unreachable.