Describe the bug
The stubs added in commit 09dd6fe have a problem of being ambiguous for the decorators. The issue stem because both overloads set the info argument with a different type, but with a default value.
This is problematic as the spec mentions
If the return types are not equivalent, overload matching is ambiguous. In this case, assume a return type of Any and stop.
Unfortunately, most type checkers don't follow this rule an instead return the first match. However, in this proposal they mention explicitly in Change number 2 that ambiguous overloads are problematic.
The fix is simple and just require removing the default from the first overload. It just require changing it to
@overload
def cached(
cache: MutableMapping[_KT, Any] | None,
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: _AbstractCondition | None = None,
info: Literal[True], # note how we removed ' = ...'
) -> Callable[[Callable[..., _R]], _cached_wrapper_info[_R]]: ...
@overload
def cachedmethod(
cache: Callable[[Any], MutableMapping[_KT, Any]],
key: Callable[..., _KT] = ...,
lock: Callable[[Any], AbstractContextManager[Any]] | None = None,
condition: Callable[[Any], _AbstractCondition] | None = None,
info: Literal[True], # note how we removed ' = ...'
) -> Callable[[Callable[..., _R]], _cachedmethod_wrapper_info[_R]]: ...
Expected result
All type checkers (specially those that follow the spec carefully) should correctly type check decorators.
Actual result
zuban treats decorated functions as Any (which is correct according to the spec).
Reproduction steps
The following code shows how the code is not correctly typed when using zuban
from typing import reveal_type
import cachetools
@cachetools.cached(cachetools.LRUCache(1))
def foo() -> str:
return "foo"
reveal_type(foo)
class A:
def __init__(self):
self.cache = cachetools.LRUCache(1)
@cachetools.cachedmethod(lambda self: self.cache)
def foo(self) -> str:
return "foo"
reveal_type(A.foo)
uvx zuban check test_decorator.py
test_decorator.py:9: note: Revealed type is "Any"
test_decorator.py:19: note: Revealed type is "Any"
Describe the bug
The stubs added in commit 09dd6fe have a problem of being ambiguous for the decorators. The issue stem because both overloads set the info argument with a different type, but with a default value.
This is problematic as the spec mentions
Unfortunately, most type checkers don't follow this rule an instead return the first match. However, in this proposal they mention explicitly in Change number 2 that ambiguous overloads are problematic.
The fix is simple and just require removing the default from the first overload. It just require changing it to
Expected result
All type checkers (specially those that follow the spec carefully) should correctly type check decorators.
Actual result
zuban treats decorated functions as
Any(which is correct according to the spec).Reproduction steps
The following code shows how the code is not correctly typed when using zuban