@@ -28,21 +28,36 @@ def meet_simple(s: Type, t: Type, default_right: bool = True) -> Type:
28
28
return s
29
29
if isinstance (s , UnionType ):
30
30
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 ()
33
33
else :
34
34
if default_right :
35
35
return t
36
36
else :
37
37
return s
38
38
39
39
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
+ """
42
49
if isinstance (t , Instance ):
43
50
if isinstance (s , Instance ):
44
51
# Only consider two classes non-disjoint if one is included in the mro
45
52
# 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
46
61
return t .type in s .type .mro or s .type in t .type .mro
47
62
if isinstance (t , UnionType ):
48
63
return any (is_overlapping_types (item , s )
0 commit comments