Skip to content

Commit

Permalink
Fix is_overlapping_types() logic for fallback instances (#7351)
Browse files Browse the repository at this point in the history
Fixes #7350

This also fixes an unrelated issue that went unnoticed because of a poor test (in that case the problem was because of a callable fallback, which is a metaclass for class objects).
  • Loading branch information
ilevkivskyi committed Aug 16, 2019
1 parent 85420a0 commit 36fcf1d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
3 changes: 3 additions & 0 deletions mypy/meet.py
Expand Up @@ -302,6 +302,9 @@ def _type_object_overlap(left: ProperType, right: ProperType) -> bool:
return False

if len(left.args) == len(right.args):
if not left.args:
# We can get here if the instance is in fact a fallback from another type.
return True
# Note: we don't really care about variance here, since the overlapping check
# is symmetric and since we want to return 'True' even for partial overlaps.
#
Expand Down
20 changes: 18 additions & 2 deletions test-data/unit/check-expressions.test
Expand Up @@ -2212,10 +2212,10 @@ Bad in subclasses # E: Non-overlapping container check (element type: "Type[Bad
from typing import List, Type

class Meta(type): ...
class OtherMeta(type): ...

class A(metaclass=Meta): ...
class B(metaclass=Meta): ...
class C: ...
class C(metaclass=OtherMeta): ...

o: Type[object]
exp: List[Meta]
Expand Down Expand Up @@ -2287,6 +2287,22 @@ if returns_1_or_2() is THREE: # E: Non-overlapping identity check (left operand
...
[builtins fixtures/bool.pyi]

[case testStrictEqualityWithALiteralNewType]
# flags: --strict-equality
from typing import NewType

UserId = NewType('UserId', int)
FileId = NewType('FileId', str)

u: UserId
f: FileId

if u == 0: # OK
...
if f == 0: # E: Non-overlapping equality check (left operand type: "FileId", right operand type: "Literal[0]")
...
[builtins fixtures/bool.pyi]

[case testUnimportedHintAny]
def f(x: Any) -> None: # E: Name 'Any' is not defined \
# N: Did you forget to import it from "typing"? (Suggestion: "from typing import Any")
Expand Down
15 changes: 15 additions & 0 deletions test-data/unit/check-overloading.test
Expand Up @@ -5058,3 +5058,18 @@ tmp/lib.pyi:1: error: Name 'overload' is not defined
tmp/lib.pyi:3: error: Name 'func' already defined on line 1
tmp/lib.pyi:3: error: Name 'overload' is not defined
main:3: note: Revealed type is 'Any'

[case testLiteralSubtypeOverlap]
from typing import overload
from typing_extensions import Literal

class MyInt(int): ...

# Strictly speaking we can't prove this is unsafe (this depends on the implementation),
# but such APIs seem like an anti-pattern anyways.
@overload
def foo(x: Literal[0]) -> None: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo(x: MyInt) -> int: ...
def foo(x):
...

0 comments on commit 36fcf1d

Please sign in to comment.