Skip to content

Commit

Permalink
Try ignoring Anys in type object callables for purposes of overload a…
Browse files Browse the repository at this point in the history
…mbiguity (python#10734)

I believe this should help with some issues that come up with python#10694.
  • Loading branch information
msullivan authored Jun 29, 2021
1 parent a8c32c9 commit 416f57b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
17 changes: 13 additions & 4 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4199,18 +4199,24 @@ def narrow_type_from_binder(self, expr: Expression, known_type: Type,
return known_type


def has_any_type(t: Type) -> bool:
def has_any_type(t: Type, ignore_in_type_obj: bool = False) -> bool:
"""Whether t contains an Any type"""
return t.accept(HasAnyType())
return t.accept(HasAnyType(ignore_in_type_obj))


class HasAnyType(types.TypeQuery[bool]):
def __init__(self) -> None:
def __init__(self, ignore_in_type_obj: bool) -> None:
super().__init__(any)
self.ignore_in_type_obj = ignore_in_type_obj

def visit_any(self, t: AnyType) -> bool:
return t.type_of_any != TypeOfAny.special_form # special forms are not real Any types

def visit_callable_type(self, t: CallableType) -> bool:
if self.ignore_in_type_obj and t.is_type_obj():
return False
return super().visit_callable_type(t)


def has_coroutine_decorator(t: Type) -> bool:
"""Whether t came from a function decorated with `@coroutine`."""
Expand Down Expand Up @@ -4408,7 +4414,10 @@ def any_causes_overload_ambiguity(items: List[CallableType],
]

for arg_idx, arg_type in enumerate(arg_types):
if has_any_type(arg_type):
# We ignore Anys in type object callables as ambiguity
# creators, since that can lead to falsely claiming ambiguity
# for overloads between Type and Callable.
if has_any_type(arg_type, ignore_in_type_obj=True):
matching_formals_unfiltered = [(item_idx, lookup[arg_idx])
for item_idx, lookup in enumerate(actual_to_formal)
if lookup[arg_idx]]
Expand Down
16 changes: 16 additions & 0 deletions test-data/unit/check-overloading.test
Original file line number Diff line number Diff line change
Expand Up @@ -5173,3 +5173,19 @@ def f2(g: G[A, Any]) -> A: ... # E: Overloaded function signatures 1 and 2 over
@overload
def f2(g: G[A, B], x: int = ...) -> B: ...
def f2(g: Any, x: int = ...) -> Any: ...

[case testOverloadTypeVsCallable]
from typing import TypeVar, Type, Callable, Any, overload
class Foo:
def __init__(self, **kwargs: Any): pass
_T = TypeVar('_T')
@overload
def register(cls: Type[_T]) -> int: ...
@overload
def register(cls: Callable[..., _T]) -> str: ...
def register(cls: Any) -> Any: return None


x = register(Foo)
reveal_type(x) # N: Revealed type is "builtins.int"
[builtins fixtures/dict.pyi]

0 comments on commit 416f57b

Please sign in to comment.