Skip to content

Commit d0bee85

Browse files
committed
Make overload checks more strict when there are multiple 'Any's
Resolves #5250 This makes the "multiple overload matches due to Any" even more strict: we now return a non-Any type only if all of the return types are the same.
1 parent 5dc7454 commit d0bee85

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

mypy/checkexpr.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
from mypy import join
3737
from mypy.meet import narrow_declared_type
3838
from mypy.maptype import map_instance_to_supertype
39-
from mypy.subtypes import is_subtype, is_equivalent, find_member, non_method_protocol_members
39+
from mypy.subtypes import is_subtype, is_proper_subtype, is_equivalent, find_member, non_method_protocol_members
4040
from mypy import applytype
4141
from mypy import erasetype
4242
from mypy.checkmember import analyze_member_access, type_object_type, bind_self
@@ -1314,12 +1314,9 @@ def infer_overload_return_type(self,
13141314
return None
13151315
elif any_causes_overload_ambiguity(matches, return_types, arg_types, arg_kinds, arg_names):
13161316
# An argument of type or containing the type 'Any' caused ambiguity.
1317-
if all(is_subtype(ret_type, return_types[-1]) and
1318-
is_subtype(return_types[-1], ret_type)
1319-
for ret_type in return_types[:-1]):
1320-
# The last match is mutually compatible with all previous ones, so it's safe
1321-
# to return that inferred type.
1322-
return return_types[-1], inferred_types[-1]
1317+
if all_same_types(return_types):
1318+
# The return types are all the same, so it's safe to return that instead of 'Any'
1319+
return return_types[0], inferred_types[0]
13231320
else:
13241321
# We give up and return 'Any'.
13251322
return self.check_call(callee=AnyType(TypeOfAny.special_form),

test-data/unit/check-overloading.test

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,8 +1400,8 @@ a: Any
14001400
b: List[Any]
14011401
c: List[str]
14021402
d: List[int]
1403-
reveal_type(f(a)) # E: Revealed type is 'builtins.list[Any]'
1404-
reveal_type(f(b)) # E: Revealed type is 'builtins.list[Any]'
1403+
reveal_type(f(a)) # E: Revealed type is 'Any'
1404+
reveal_type(f(b)) # E: Revealed type is 'Any'
14051405
reveal_type(f(c)) # E: Revealed type is 'builtins.list[Any]'
14061406
reveal_type(f(d)) # E: Revealed type is 'builtins.list[builtins.int]'
14071407

@@ -1443,6 +1443,54 @@ reveal_type(f(**a)) # E: Revealed type is 'Any'
14431443

14441444
[builtins fixtures/dict.pyi]
14451445

1446+
[case testOverloadWithOverlappingItemsAndAnyArgument12]
1447+
from typing import overload, Any
1448+
1449+
@overload
1450+
def f(x: int) -> Any: ...
1451+
@overload
1452+
def f(x: str) -> str: ...
1453+
def f(x): pass
1454+
1455+
a: Any
1456+
reveal_type(f(a)) # E: Revealed type is 'Any'
1457+
1458+
[case testOverloadWithOverlappingItemsAndAnyArgument13]
1459+
from typing import Any, overload, TypeVar, Generic
1460+
1461+
class slice: pass
1462+
1463+
T = TypeVar('T')
1464+
class A(Generic[T]):
1465+
@overload
1466+
def f(self, x: int) -> T: ...
1467+
@overload
1468+
def f(self, x: slice) -> A[T]: ...
1469+
def f(self, x): ...
1470+
1471+
i: Any
1472+
a: A[Any]
1473+
reveal_type(a.f(i)) # E: Revealed type is 'Any'
1474+
1475+
[case testOverloadWithOverlappingItemsAndAnyArgument14]
1476+
from typing import overload, Any, Union
1477+
1478+
@overload
1479+
def f(x: int) -> str: ...
1480+
@overload
1481+
def f(x: str) -> str: ...
1482+
def f(x): pass
1483+
1484+
@overload
1485+
def g(x: int) -> Union[str, int]: ...
1486+
@overload
1487+
def g(x: str) -> Union[int, str]: ...
1488+
def g(x): pass
1489+
1490+
a: Any
1491+
reveal_type(f(a)) # E: Revealed type is 'builtins.str'
1492+
reveal_type(g(a)) # E: Revealed type is 'Union[builtins.str, builtins.int]'
1493+
14461494
[case testOverloadOnOverloadWithType]
14471495
from typing import Any, Type, TypeVar, overload
14481496
from mod import MyInt

0 commit comments

Comments
 (0)