Closed
Description
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 thecase
body (everything isTuple[, fallback=__main__.Foo]
) - Define
Foo
as plain classclass Foo: pass
(everything is__main__.Foo
) - Remove the union, i.e. type the arg as
some: Foo
rather thansome: 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