python / mypy

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

functools.partial incorrectly handles constrained generic function arguments #17411

Open tamird opened 1 week ago

tamird commented 1 week ago

Looks like the generic return type is being resolved even before a value of a concrete type is provided.

from typing import Type, TypeVar
import functools

T = TypeVar("T", int, str)

def foo(a: int, b: str, t: Type[T]) -> T: ...

p1 = functools.partial(foo, 1, 2)  # E: Argument 2 to "foo" has incompatible type "int"; expected "str"
p2 = functools.partial(foo, "hello", "world")  # E: Argument 1 to "foo" has incompatible type "str"; expected "int"
p3 = functools.partial(foo, 1, "hello")

reveal_type(p3)  # N: Revealed type is "functools.partial[builtins.int]"  # should still be generic
reveal_type(p3(int))  # N: Revealed type is "builtins.int"
reveal_type(p3(str))  # N: Revealed type is "builtins.int" \
                      # E: Argument 1 to "foo" has incompatible type "Type[str]"; expected "Type[int]"
reveal_type(p3(list))  # N: Revealed type is "builtins.int" \
                       # E: Argument 1 to "foo" has incompatible type "Type[List[Any]]"; expected "Type[int]"

See #17297 for a runnable test case.