From 2fd3c9052e0e4a97f9092220e379dfd791560ee5 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 9 Jul 2018 22:09:49 +0100 Subject: [PATCH 1/2] Implement a basic meet for overloaded types --- mypy/meet.py | 12 +++++++++++- test-data/unit/check-overloading.test | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mypy/meet.py b/mypy/meet.py index 32772f4801c10..4a543ff141c85 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -5,7 +5,7 @@ from mypy.types import ( Type, AnyType, TypeVisitor, UnboundType, NoneTyp, TypeVarType, Instance, CallableType, TupleType, TypedDictType, ErasedType, UnionType, PartialType, DeletedType, - UninhabitedType, TypeType, TypeOfAny + UninhabitedType, TypeType, TypeOfAny, Overloaded, FunctionLike ) from mypy.subtypes import is_equivalent, is_subtype, is_protocol_implementation @@ -314,6 +314,16 @@ def visit_callable_type(self, t: CallableType) -> Type: else: return self.default(self.s) + def visit_overloaded(self, t: Overloaded) -> Type: + # TODO: Implement a better algorithm that covers at least the same cases + # as TypeJoinVisitor.visit_overloaded(). + s = self.s + if isinstance(s, FunctionLike): + if s.items() == t.items(): + return Overloaded(t.items()) + return meet_types(t.fallback, s.fallback) + return meet_types(t.fallback, s) + def visit_tuple_type(self, t: TupleType) -> Type: if isinstance(self.s, TupleType) and self.s.length() == t.length(): items = [] # type: List[Type] diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 7e388cbaa373a..4e0fbbc8df165 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -4078,3 +4078,25 @@ g(3) # E: No overload variant of "g" matches argument type "int" \ # N: def g(x: A) -> None \ # N: def g(x: B) -> None \ # N: def g(x: C) -> None + +[case testOverloadedInIter] +from lib import f, g + +for fun in [f, g]: + reveal_type(fun) # E: Revealed type is 'Overload(def (x: builtins.int) -> builtins.str, def (x: builtins.str) -> builtins.int)' +[file lib.pyi] +from typing import overload + +@overload +def f(x: int) -> str: ... +@overload +def f(x: str) -> int: ... + +@overload +def g(x: int) -> str: ... +@overload +def g(x: str) -> int: ... + +[builtins fixtures/list.pyi] +[typing fixtures/typing-full.pyi] +[out] From 592d9e6a5e22e22d2c2bc2a9b631f10c44899dc3 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 9 Jul 2018 22:22:32 +0100 Subject: [PATCH 2/2] Slightly better algorithm --- mypy/meet.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mypy/meet.py b/mypy/meet.py index 4a543ff141c85..db0ade90ebb85 100644 --- a/mypy/meet.py +++ b/mypy/meet.py @@ -321,7 +321,12 @@ def visit_overloaded(self, t: Overloaded) -> Type: if isinstance(s, FunctionLike): if s.items() == t.items(): return Overloaded(t.items()) - return meet_types(t.fallback, s.fallback) + elif is_subtype(s, t): + return s + elif is_subtype(t, s): + return t + else: + return meet_types(t.fallback, s.fallback) return meet_types(t.fallback, s) def visit_tuple_type(self, t: TupleType) -> Type: