Apologies in advance if this duplicates an existing issue. I reviewed a bunch, but none seemed like an exact match. #15015 and #15737 were the closest.
https://mypy-play.net/?mypy=latest&python=3.13&gist=24cbdbfe356ffc9d12b75d5960dc2c4c
from collections.abc import Callable
from typing import Any, TypeVar, overload
T = TypeVar('T')
def call(func: Callable[..., T], *args, **kwargs) -> T:
return func(*args, **kwargs)
@overload
def f(x: int) -> int:
...
@overload
def f(x: str) -> str:
...
def f(x):
return x
reveal_type(call(f, 1))
reveal_type(call(f, "a"))
Expected result: I expected that mypy would either:
- evaluate the overload for each call and reveal
int for the first call, str for the second; or
- raise an error that
T can't be resolved.
- (or maybe reveal
int | str? or even Any? would prefer one of the first two though.)
Actual result: mypy silently uses the return type from the first overload, does not raise any error.
main.py:19: note: Revealed type is "int"
main.py:20: note: Revealed type is "int"
Success: no issues found in 1 source file
My actual use case is that I wanted to write:
# requires: boto3, boto3-stubs[logs]
import functools
import boto3
get_client = functools.cache(boto3.Session().client)
reveal_type(get_client('logs'))
# expected: Revealed type is "mypy_boto3_logs.client.CloudWatchLogsClient"
# actual: Revealed type is "mypy_boto3_accessanalyzer.client.AccessAnalyzerClient" if mypy-boto3-accessanalyzer is installed, "Any" otherwise
boto3.Session.client is an overloaded method. As above, mypy didn't raise any error, but just took the first overload.
The relevant declaration of functools.cache: https://github.com/python/typeshed/blob/1d3abc42077c2ea47985363a4fab387357f3aa77/stdlib/functools.pyi#L263
def cache(user_function: Callable[..., _T], /) -> _lru_cache_wrapper[_T]: ...
If the entire Callable is used (with or without ParamSpec), mypy is able to see the overloads. I don't need the other methods of _lru_cache_wrapper, so this workaround works for me:
from collections.abc import Callable
import functools
from typing import Any, TypeVar, cast
import boto3
T = TypeVar('T', bound=Callable[..., Any])
def cache(func: T) -> T:
return cast(T, functools.cache(func))
get_client = cache(boto3.Session().client)
reveal_type(get_client('logs'))
# Revealed type is "mypy_boto3_logs.client.CloudWatchLogsClient"
Thank you for maintaining mypy!
Apologies in advance if this duplicates an existing issue. I reviewed a bunch, but none seemed like an exact match. #15015 and #15737 were the closest.
https://mypy-play.net/?mypy=latest&python=3.13&gist=24cbdbfe356ffc9d12b75d5960dc2c4c
Expected result: I expected that mypy would either:
intfor the first call,strfor the second; orTcan't be resolved.int | str? or evenAny? would prefer one of the first two though.)Actual result: mypy silently uses the return type from the first overload, does not raise any error.
My actual use case is that I wanted to write:
boto3.Session.clientis an overloaded method. As above, mypy didn't raise any error, but just took the first overload.The relevant declaration of
functools.cache: https://github.com/python/typeshed/blob/1d3abc42077c2ea47985363a4fab387357f3aa77/stdlib/functools.pyi#L263If the entire Callable is used (with or without ParamSpec), mypy is able to see the overloads. I don't need the other methods of
_lru_cache_wrapper, so this workaround works for me:Thank you for maintaining mypy!