Skip to content

Commit 2aaf065

Browse files
committed
Use type promotions in meet_simple
Fixes #1206.
1 parent 3705ca2 commit 2aaf065

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

mypy/meet.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,36 @@ def meet_simple(s: Type, t: Type, default_right: bool = True) -> Type:
2828
return s
2929
if isinstance(s, UnionType):
3030
return UnionType.make_simplified_union([meet_types(x, t) for x in s.items])
31-
elif not is_overlapping_types(s, t):
32-
return Void()
31+
elif not is_overlapping_types(s, t, use_promotions=True):
32+
return NoneTyp()
3333
else:
3434
if default_right:
3535
return t
3636
else:
3737
return s
3838

3939

40-
def is_overlapping_types(t: Type, s: Type) -> bool:
41-
"""Can a value of type t be a value of type s, or vice versa?"""
40+
def is_overlapping_types(t: Type, s: Type, use_promotions: bool = False) -> bool:
41+
"""Can a value of type t be a value of type s, or vice versa?
42+
43+
Note that this effectively checks against erased types, since X[Any] is always
44+
compatible with X[T].
45+
46+
If use_promitions is True, also consider type promotions (int and
47+
float would only be overlapping if it's True).
48+
"""
4249
if isinstance(t, Instance):
4350
if isinstance(s, Instance):
4451
# Only consider two classes non-disjoint if one is included in the mro
4552
# of another.
53+
if use_promotions:
54+
# Consider cases like int vs float to be overlapping where
55+
# there is only a type promition relationship but not proper
56+
# subclassing.
57+
if t.type._promote and is_overlapping_types(t.type._promote, s):
58+
return True
59+
if s.type._promote and is_overlapping_types(s.type._promote, t):
60+
return True
4661
return t.type in s.type.mro or s.type in t.type.mro
4762
if isinstance(t, UnionType):
4863
return any(is_overlapping_types(item, s)

mypy/test/data/check-type-promotion.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,15 @@ f(1)
2525
def f(x: bytes) -> None: pass
2626
f(bytearray())
2727
[builtins fixtures/primitives.py]
28+
29+
[case testNarrowingDownFromPromoteTargetType]
30+
y = 0.0
31+
y = 1
32+
y() # E: "int" not callable
33+
[builtins fixtures/primitives.py]
34+
35+
[case testNarrowingDownFromPromoteTargetType2]
36+
y = 0.0
37+
y = 1
38+
y.x # E: "int" has no attribute "x"
39+
[builtins fixtures/primitives.py]

0 commit comments

Comments
 (0)