Skip to content

Commit 94309a1

Browse files
JukkaLmsullivan
authored andcommitted
Don't always infer unions for conditional expressions (#5095)
Use a join for type of a conditional expression unless the type context is a union type. A recent change (#5041) modified the type to always use a union, but this caused many problems in internal Dropbox repos that we aren't ready to fix yet.
1 parent 7411cbe commit 94309a1

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

mypy/checkexpr.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2357,7 +2357,14 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type:
23572357
# branch's type.
23582358
else_type = self.analyze_cond_branch(else_map, e.else_expr, context=if_type)
23592359

2360-
res = UnionType.make_simplified_union([if_type, else_type])
2360+
# Only create a union type if the type context is a union, to be mostly
2361+
# compatible with older mypy versions where we always did a join.
2362+
#
2363+
# TODO: Always create a union or at least in more cases?
2364+
if isinstance(self.type_context[-1], UnionType):
2365+
res = UnionType.make_simplified_union([if_type, else_type])
2366+
else:
2367+
res = join.join_types(if_type, else_type)
23612368

23622369
return res
23632370

test-data/unit/check-expressions.test

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,8 +1449,11 @@ x = ['x'] # E: List item 0 has incompatible type "str"; expected "int"
14491449
[builtins fixtures/list.pyi]
14501450

14511451
[case testConditionalExpressionUnion]
1452+
from typing import Union
14521453
reveal_type(1 if bool() else 2) # E: Revealed type is 'builtins.int'
1453-
reveal_type(1 if bool() else '') # E: Revealed type is 'Union[builtins.int, builtins.str]'
1454+
reveal_type(1 if bool() else '') # E: Revealed type is 'builtins.object'
1455+
x: Union[int, str] = reveal_type(1 if bool() else '') \
1456+
# E: Revealed type is 'Union[builtins.int, builtins.str]'
14541457
class A:
14551458
pass
14561459
class B(A):
@@ -1464,12 +1467,18 @@ b = B()
14641467
c = C()
14651468
d = D()
14661469
reveal_type(a if bool() else b) # E: Revealed type is '__main__.A'
1467-
reveal_type(b if bool() else c) # E: Revealed type is 'Union[__main__.B, __main__.C]'
1468-
reveal_type(c if bool() else b) # E: Revealed type is 'Union[__main__.C, __main__.B]'
1469-
reveal_type(c if bool() else a) # E: Revealed type is 'Union[__main__.C, __main__.A]'
1470-
reveal_type(d if bool() else b) # E: Revealed type is 'Union[__main__.D, __main__.B]'
1470+
reveal_type(b if bool() else c) # E: Revealed type is 'builtins.object'
1471+
reveal_type(c if bool() else b) # E: Revealed type is 'builtins.object'
1472+
reveal_type(c if bool() else a) # E: Revealed type is 'builtins.object'
1473+
reveal_type(d if bool() else b) # E: Revealed type is '__main__.A'
14711474
[builtins fixtures/bool.pyi]
14721475

1476+
[case testConditionalExpressionUnionWithAny]
1477+
from typing import Union, Any
1478+
a: Any
1479+
x: Union[int, str] = reveal_type(a if int() else 1) # E: Revealed type is 'Union[Any, builtins.int]'
1480+
reveal_type(a if int() else 1) # E: Revealed type is 'Any'
1481+
14731482

14741483
-- Special cases
14751484
-- -------------

test-data/unit/check-functions.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,8 +2064,8 @@ def f() -> None:
20642064
def g(x: int) -> None:
20652065
pass
20662066
h = f if bool() else g
2067-
reveal_type(h) # E: Revealed type is 'Union[def (), def (x: builtins.int)]'
2068-
h(7) # E: Too many arguments for "f"
2067+
reveal_type(h) # E: Revealed type is 'builtins.function'
2068+
h(7) # E: Cannot call function of unknown type
20692069
[builtins fixtures/bool.pyi]
20702070

20712071
-- Positional-only arguments

test-data/unit/check-optional.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ def lookup_field(name, obj):
385385
attr = None
386386

387387
[case testTernaryWithNone]
388-
reveal_type(None if bool() else 0) # E: Revealed type is 'Union[None, builtins.int]'
388+
reveal_type(None if bool() else 0) # E: Revealed type is 'Union[builtins.int, None]'
389389
[builtins fixtures/bool.pyi]
390390

391391
[case testListWithNone]

0 commit comments

Comments
 (0)