Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix overload handling with union types in signatures #3300

Merged
merged 6 commits into from Sep 6, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 7 additions & 12 deletions mypy/subtypes.py
Expand Up @@ -717,19 +717,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)
4 changes: 2 additions & 2 deletions mypy/test/testtypes.py
Expand Up @@ -175,11 +175,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

Expand Down
14 changes: 14 additions & 0 deletions test-data/unit/check-optional.test
Expand Up @@ -595,6 +595,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:
Expand Down