Skip to content

Commit

Permalink
Use type promotions in meet_simple
Browse files Browse the repository at this point in the history
Fixes #1206.
  • Loading branch information
JukkaL committed Feb 4, 2016
1 parent 3705ca2 commit 2aaf065
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
23 changes: 19 additions & 4 deletions mypy/meet.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,36 @@ def meet_simple(s: Type, t: Type, default_right: bool = True) -> Type:
return s
if isinstance(s, UnionType):
return UnionType.make_simplified_union([meet_types(x, t) for x in s.items])
elif not is_overlapping_types(s, t):
return Void()
elif not is_overlapping_types(s, t, use_promotions=True):
return NoneTyp()
else:
if default_right:
return t
else:
return s


def is_overlapping_types(t: Type, s: Type) -> bool:
"""Can a value of type t be a value of type s, or vice versa?"""
def is_overlapping_types(t: Type, s: Type, use_promotions: bool = False) -> bool:
"""Can a value of type t be a value of type s, or vice versa?
Note that this effectively checks against erased types, since X[Any] is always
compatible with X[T].
If use_promitions is True, also consider type promotions (int and
float would only be overlapping if it's True).
"""
if isinstance(t, Instance):
if isinstance(s, Instance):
# Only consider two classes non-disjoint if one is included in the mro
# of another.
if use_promotions:
# Consider cases like int vs float to be overlapping where
# there is only a type promition relationship but not proper
# subclassing.
if t.type._promote and is_overlapping_types(t.type._promote, s):
return True
if s.type._promote and is_overlapping_types(s.type._promote, t):
return True
return t.type in s.type.mro or s.type in t.type.mro
if isinstance(t, UnionType):
return any(is_overlapping_types(item, s)
Expand Down
12 changes: 12 additions & 0 deletions mypy/test/data/check-type-promotion.test
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,15 @@ f(1)
def f(x: bytes) -> None: pass
f(bytearray())
[builtins fixtures/primitives.py]

[case testNarrowingDownFromPromoteTargetType]
y = 0.0
y = 1
y() # E: "int" not callable
[builtins fixtures/primitives.py]

[case testNarrowingDownFromPromoteTargetType2]
y = 0.0
y = 1
y.x # E: "int" has no attribute "x"
[builtins fixtures/primitives.py]

0 comments on commit 2aaf065

Please sign in to comment.