Skip to content

Commit

Permalink
Fix crash with overload and callable object decorators
Browse files Browse the repository at this point in the history
Fixes the crash in #8356, as identified by @pranavrajpal

Note that we still don't support the singledispatch in that issue, since
we get 'overloaded function has no attribute "register"', but that's
much easier to work around than a crash.
  • Loading branch information
hauntsaninja committed Nov 27, 2021
1 parent d7c4e69 commit 085b88f
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
10 changes: 8 additions & 2 deletions mypy/checker.py
Expand Up @@ -507,8 +507,14 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
# decorator or if the implementation is untyped -- we gave up on the types.
inner_type = get_proper_type(inner_type)
if inner_type is not None and not isinstance(inner_type, AnyType):
assert isinstance(inner_type, CallableType)
impl_type = inner_type
if isinstance(inner_type, CallableType):
impl_type = inner_type
elif isinstance(inner_type, Instance):
inner_call = find_member('__call__', inner_type, inner_type, is_operator=True)
assert inner_call is not None
impl_type = cast(CallableType, inner_call)
else:
assert False

is_descriptor_get = defn.info and defn.name == "__get__"
for i, item in enumerate(defn.items):
Expand Down
44 changes: 44 additions & 0 deletions test-data/unit/check-overloading.test
Expand Up @@ -5339,3 +5339,47 @@ def register(cls: Any) -> Any: return None
x = register(Foo)
reveal_type(x) # N: Revealed type is "builtins.int"
[builtins fixtures/dict.pyi]


[case testOverloadWithObjectDecorator]
from typing import Any, Callable, Union, overload

class A:
def __call__(self, *arg, **kwargs) -> None: ...

def dec_a(f: Callable[..., Any]) -> A:
return A()

@overload
def f_a(arg: int) -> None: ...
@overload
def f_a(arg: str) -> None: ...
@dec_a
def f_a(arg): ...

class B:
def __call__(self, arg: Union[int, str]) -> None: ...

def dec_b(f: Callable[..., Any]) -> B:
return B()

@overload
def f_b(arg: int) -> None: ...
@overload
def f_b(arg: str) -> None: ...
@dec_b
def f_b(arg): ...

class C:
def __call__(self, arg: int) -> None: ...

def dec_c(f: Callable[..., Any]) -> C:
return C()

@overload
def f_c(arg: int) -> None: ...
@overload
def f_c(arg: str) -> None: ...
@dec_c # E: Overloaded function implementation does not accept all possible arguments of signature 2
def f_c(arg): ...
[builtins fixtures/dict.pyi]

0 comments on commit 085b88f

Please sign in to comment.