Skip to content

match doesn't deduce type of tuple member from guard clause #12532

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bkovitz opened this issue Apr 6, 2022 · 1 comment · Fixed by #18448
Closed

match doesn't deduce type of tuple member from guard clause #12532

bkovitz opened this issue Apr 6, 2022 · 1 comment · Fixed by #18448
Labels
bug mypy got something wrong topic-match-statement Python 3.10's match statement

Comments

@bkovitz
Copy link

bkovitz commented Apr 6, 2022

Bug Report

match can't determine type of an element of a tuple guarded with isinstance, if the variable holding the tuple has type Any.

To Reproduce

from typing import Any

e: Any = ('x',)
match e:
    case (a,) if isinstance(a, str):
        print('HERE', e)

Expected Behavior

This code should pass type-check. mypy should be able to determine the type of "a" because the isinstance guard implies that "a" must be a str.

Actual Behavior

$ mypy --python-version 3.10 x.py
x.py:5: error: Cannot determine type of "a"
Found 1 error in 1 file (checked 1 source file)

Variations

If e is given no declared type, like this:

e = ('x',)

then mypy reports no errors.

If e is declared to be a tuple whose members are unspecified, like this:

e: Tuple = ('x',)

then mypy reports no errors.

Environment

  • Mypy version used: 0.942
  • Mypy command-line flags: --python-version 3.10 x.py
  • Mypy configuration options from mypy.ini (and other config files): (none)
  • Python version used: 3.10.2
  • Operating system and version: Ubuntu 18.04
@bkovitz bkovitz added the bug mypy got something wrong label Apr 6, 2022
@JelleZijlstra JelleZijlstra added the topic-match-statement Python 3.10's match statement label Apr 6, 2022
@erictraut
Copy link

There is a question about whether Any should be narrowed in this case. In general, Any is not narrowed, but there are a few exceptions to this rule. In particular, isinstance and issubclass do support narrowing of Any in all Python type checkers AFAIK. The question is whether type narrowing in match statements should also be an exception to this rule. Here's the discussion we had on this topic for pyright. In the end, we concluded that match should narrow Any, at least for class patterns.

Your sample above is doing a class-based check but it's not using a class pattern. This is a more idiomatic way to use match for this use case:

def func(e: Any):
    match e:
        case (str() as a,):
            reveal_type(a)

Mypy appears to have a different bug in this case though. It determines that the case statement is unreachable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-match-statement Python 3.10's match statement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants