diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 5dfbc7c405bc..049da8a07228 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -945,19 +945,14 @@ def visit_type_type(self, left: TypeType) -> bool: return False -def is_more_precise(t: Type, s: Type) -> bool: - """Check if t is a more precise type than s. +def is_more_precise(left: Type, right: Type) -> bool: + """Check if left is a more precise type than right. - A t is a proper subtype of s, t is also more precise than s. Also, if - s is Any, t is more precise than s for any t. Finally, if t is the same - type as s, t is more precise than s. + A left is a proper subtype of right, left is also more precise than + right. Also, if right is Any, left is more precise than right, for + any left. """ # TODO Should List[int] be more precise than List[Any]? - if isinstance(s, AnyType): + if isinstance(right, AnyType): return True - if isinstance(s, Instance): - if isinstance(t, CallableType): - # Fall back to subclass check and ignore other properties of the callable. - return is_proper_subtype(t.fallback, s) - return is_proper_subtype(t, s) - return sametypes.is_same_type(t, s) + return is_proper_subtype(left, right) diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index f85a9aeb4996..3c7b6189458d 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -176,11 +176,11 @@ def test_is_more_precise(self) -> None: assert_true(is_more_precise(fx.b, fx.anyt)) assert_true(is_more_precise(self.tuple(fx.b, fx.a), self.tuple(fx.b, fx.a))) + assert_true(is_more_precise(self.tuple(fx.b, fx.b), + self.tuple(fx.b, fx.a))) assert_false(is_more_precise(fx.a, fx.b)) assert_false(is_more_precise(fx.anyt, fx.b)) - assert_false(is_more_precise(self.tuple(fx.b, fx.b), - self.tuple(fx.b, fx.a))) # is_proper_subtype diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index 545df7b31147..138643269e89 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -620,6 +620,20 @@ reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins y: Optional[Union[int, None]] reveal_type(y) # E: Revealed type is 'Union[builtins.int, builtins.None]' +[case testOverloadWithNoneAndOptional] +from typing import overload, Optional + +@overload +def f(x: int) -> str: ... +@overload +def f(x: Optional[int]) -> Optional[str]: ... +def f(x): return x + +reveal_type(f(1)) # E: Revealed type is 'builtins.str' +reveal_type(f(None)) # E: Revealed type is 'Union[builtins.str, builtins.None]' +x: Optional[int] +reveal_type(f(x)) # E: Revealed type is 'Union[builtins.str, builtins.None]' + [case testUnionTruthinessTracking] from typing import Optional, Any def test_or_shortcut(value: Optional[Any]) -> None: