8000 Fix simplification of some unions · python/mypy@f43fd8f · GitHub
[go: up one dir, main page]

Skip to content

Commit f43fd8f

Browse files
committed
Fix simplification of some unions
In particular, this helps with classes that have Any base classes. This is enough to fix #2712. This is almost a subset of #2714 and should land before that, as this should cause less disruption.
1 parent 234297c commit f43fd8f

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

mypy/types.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,13 +1034,18 @@ def make_simplified_union(items: List[Type], line: int = -1, column: int = -1) -
10341034
return AnyType()
10351035

10361036
from mypy.subtypes import is_subtype
1037+
from mypy.sametypes import is_same_type
1038+
10371039
removed = set() # type: Set[int]
10381040
for i, ti in enumerate(items):
10391041
if i in removed: continue
10401042
# Keep track of the truishness info for deleted subtypes which can be relevant
10411043
cbt = cbf = False
10421044
for j, tj in enumerate(items):
1043-
if i != j and is_subtype(tj, ti):
1045+
if (i != j
1046+
and is_subtype(tj, ti)
1047+
and (not (isinstance(tj, Instance) and tj.type.fallback_to_any)
1048+
or is_same_type(ti, tj))):
10441049
removed.add(j)
10451050
cbt = cbt or tj.can_be_true
10461051
cbf = cbf or tj.can_be_false

test-data/unit/check-optional.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,3 +525,22 @@ f = None # type: Optional[Callable[[int], None]]
525525
f = lambda x: None
526526
f(0)
527527
[builtins fixtures/function.pyi]
528+
529+
[case testUnionSimplificationWithStrictOptional]
530+
from typing import Any, TypeVar, Union
531+
class C(Any): pass
532+
T = TypeVar('T')
533+
S = TypeVar('S')
534+
def u(x: T, y: S) -> Union[S, T]: pass
535+
a = None # type: Any
536+
537+
# Test both orders
538+
reveal_type(u(C(), None)) # E: Revealed type is 'Union[builtins.None, __main__.C*]'
539+
reveal_type(u(None, C())) # E: Revealed type is 'Union[__main__.C*, builtins.None]'
540+
541+
# This will be fixed later
542+
reveal_type(u(a, None)) # E: Revealed type is 'Any'
543+
reveal_type(u(None, a)) # E: Revealed type is 'Any'
544+
545+
reveal_type(u(1, None)) # E: Revealed type is 'Union[builtins.None, builtins.int*]'
546+
reveal_type(u(None, 1)) # E: Revealed type is 'Union[builtins.int*, builtins.None]'

test-data/unit/check-unions.test

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,52 @@ if foo():
168168
def g(x: Union[int, str, bytes]) -> None: pass
169169
else:
170170
def g(x: Union[int, str]) -> None: pass # E: All conditional function variants must have identical signatures
171+
172+
[case testUnionSimplificationSpecialCases]
173+
from typing import Any, TypeVar, Union
174+
175+
class C(Any): pass
176+
177+
T = TypeVar('T')
178+
S = TypeVar('S')
179+
def u(x: T, y: S) -> Union[S, T]: pass
180+
181+
a = None # type: Any
182+
183+
reveal_type(u(C(), None)) # E: Revealed type is '__main__.C*'
184+
reveal_type(u(None, C())) # E: Revealed type is '__main__.C*'
185+
186+
# This will be fixed later
187+
reveal_type(u(C(), a)) # E: Revealed type is 'Any'
188+
reveal_type(u(a, C())) # E: Revealed type is 'Any'
189+
190+
reveal_type(u(C(), C())) # E: Revealed type is '__main__.C*'
191+
reveal_type(u(a, a)) # E: Revealed type is 'Any'
192+
193+
[case testUnionSimplificationSpecialCase2]
194+
from typing import Any, TypeVar, Union
195+
196+
class C(Any): pass
197+
198+
T = TypeVar('T')
199+
S = TypeVar('S')
200+
def u(x: T, y: S) -> Union[S, T]: pass
201+
202+
def f(x: T) -> None:
203+
reveal_type(u(C(), x)) # E: Revealed type is 'Union[T`-1, __main__.C*]'
204+
reveal_type(u(x, C())) # E: Revealed type is 'Union[__main__.C*, T`-1]'
205+
206+
[case testUnionSimplificationSpecialCase3]
207+
from typing import Any, TypeVar, Generic, Union
208+
209+
class C(Any): pass
210+
211+
V = TypeVar('V')
212+
T = TypeVar('T')
213+
214+
class M(Generic[V]):
215+
def get(self, default: T) -> Union[V, T]: ...
216+
217+
def f(x: M[C]) -> None:
218+
y = x.get(None)
219+
reveal_type(y) # E: Revealed type is '__main__.C'

0 commit comments

Comments
 (0)
0