Skip to content
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

capture_pattern binding type mismatches namedtuple type from Union #14501

Open
enigma opened this issue Jan 21, 2023 · 1 comment
Open

capture_pattern binding type mismatches namedtuple type from Union #14501

enigma opened this issue Jan 21, 2023 · 1 comment
Labels
bug mypy got something wrong topic-match-statement Python 3.10's match statement topic-named-tuple

Comments

@enigma
Copy link

enigma commented Jan 21, 2023

Bug Report

When matching on a union between a named tuple and something else, class/as pattern binds to a type different than the named tuple.

That is, the body of case Foo() as foo: will produce different values for reveal_type(Foo()) and reveal_type(foo).

To Reproduce

Playground link. Here for clarity:

from typing import NamedTuple
from typing_extensions import reveal_type

class Foo(NamedTuple): pass

def print_foo(foo: Foo): pass

def broken_match(some: Foo | None):
    reveal_type(some) # Union[Tuple[, fallback=__main__.Foo], None]
    match some:
        case Foo() as foo:
            # Uncommenting this works with *any* Foo definition
            #foo = some
            
            reveal_type(foo)       # __main__.Foo
            reveal_type(some)      # Tuple[, fallback=__main__.Foo]
            
            reveal_type(Foo())     # Tuple[, fallback=__main__.Foo]
            reveal_type(print_foo) # def (foo: Tuple[, fallback=__main__.Foo]) -> Any

            # Errors with: Argument 1 to "print_foo" has incompatible type "Foo"; expected "Foo"
            print_foo(foo) 
        case _:
            assert False, "nevermind"

Expected Behavior

foo should reveal whatever type Foo() reveals, and this program should type check successfully.

The program type checks if I do any of the following changes:

  • Assign foo = some inside the case body (everything is Tuple[, fallback=__main__.Foo])
  • Define Foo as plain class class Foo: pass (everything is __main__.Foo)
  • Remove the union, i.e. type the arg as some: Foo rather than some: Foo | None

Actual Behavior

main.py:15: note: Revealed type is "Union[Tuple[, fallback=__main__.Foo], None]"
main.py:21: note: Revealed type is "__main__.Foo"
main.py:22: note: Revealed type is "Tuple[, fallback=__main__.Foo]"
main.py:24: note: Revealed type is "Tuple[, fallback=__main__.Foo]"
main.py:25: note: Revealed type is "def (foo: Tuple[, fallback=__main__.Foo]) -> Any"
main.py:28: error: Argument 1 to "print_foo" has incompatible type "Foo"; expected "Foo"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

The fact it has the same name in the error is particularly confusing.

Your Environment

See playground.

  • Mypy version used: 0.991
  • Python version used: 3.11
@enigma enigma added the bug mypy got something wrong label Jan 21, 2023
@AlexWaygood AlexWaygood added topic-match-statement Python 3.10's match statement topic-named-tuple labels Jan 22, 2023
@enigma
Copy link
Author

enigma commented Jan 22, 2023

Possible duplicate: #13744

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 topic-named-tuple
Projects
None yet
Development

No branches or pull requests

2 participants