diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 0e349a436dab..463d274b02df 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2357,7 +2357,14 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type: # branch's type. else_type = self.analyze_cond_branch(else_map, e.else_expr, context=if_type) - res = UnionType.make_simplified_union([if_type, else_type]) + # Only create a union type if the type context is a union, to be mostly + # compatible with older mypy versions where we always did a join. + # + # TODO: Always create a union or at least in more cases? + if isinstance(self.type_context[-1], UnionType): + res = UnionType.make_simplified_union([if_type, else_type]) + else: + res = join.join_types(if_type, else_type) return res diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 193b6cd5233f..5772238e3fa3 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1449,8 +1449,11 @@ x = ['x'] # E: List item 0 has incompatible type "str"; expected "int" [builtins fixtures/list.pyi] [case testConditionalExpressionUnion] +from typing import Union reveal_type(1 if bool() else 2) # E: Revealed type is 'builtins.int' -reveal_type(1 if bool() else '') # E: Revealed type is 'Union[builtins.int, builtins.str]' +reveal_type(1 if bool() else '') # E: Revealed type is 'builtins.object' +x: Union[int, str] = reveal_type(1 if bool() else '') \ + # E: Revealed type is 'Union[builtins.int, builtins.str]' class A: pass class B(A): @@ -1464,12 +1467,18 @@ b = B() c = C() d = D() reveal_type(a if bool() else b) # E: Revealed type is '__main__.A' -reveal_type(b if bool() else c) # E: Revealed type is 'Union[__main__.B, __main__.C]' -reveal_type(c if bool() else b) # E: Revealed type is 'Union[__main__.C, __main__.B]' -reveal_type(c if bool() else a) # E: Revealed type is 'Union[__main__.C, __main__.A]' -reveal_type(d if bool() else b) # E: Revealed type is 'Union[__main__.D, __main__.B]' +reveal_type(b if bool() else c) # E: Revealed type is 'builtins.object' +reveal_type(c if bool() else b) # E: Revealed type is 'builtins.object' +reveal_type(c if bool() else a) # E: Revealed type is 'builtins.object' +reveal_type(d if bool() else b) # E: Revealed type is '__main__.A' [builtins fixtures/bool.pyi] +[case testConditionalExpressionUnionWithAny] +from typing import Union, Any +a: Any +x: Union[int, str] = reveal_type(a if int() else 1) # E: Revealed type is 'Union[Any, builtins.int]' +reveal_type(a if int() else 1) # E: Revealed type is 'Any' + -- Special cases -- ------------- diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index cbad4baa95a2..6817b110b3e0 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -2064,8 +2064,8 @@ def f() -> None: def g(x: int) -> None: pass h = f if bool() else g -reveal_type(h) # E: Revealed type is 'Union[def (), def (x: builtins.int)]' -h(7) # E: Too many arguments for "f" +reveal_type(h) # E: Revealed type is 'builtins.function' +h(7) # E: Cannot call function of unknown type [builtins fixtures/bool.pyi] -- Positional-only arguments diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index 44c83f973a5e..55345d11b996 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -385,7 +385,7 @@ def lookup_field(name, obj): attr = None [case testTernaryWithNone] -reveal_type(None if bool() else 0) # E: Revealed type is 'Union[None, builtins.int]' +reveal_type(None if bool() else 0) # E: Revealed type is 'Union[builtins.int, None]' [builtins fixtures/bool.pyi] [case testListWithNone]