Skip to content

Commit 049dbf0

Browse files
authored
Avoid unnecessary sum type expansion when narrowing (#22252)
conditional_types already expands bool and enum types when the target is a matching literal. Authored by Codex
1 parent 81afa82 commit 049dbf0

2 files changed

Lines changed: 19 additions & 18 deletions

File tree

‎mypy/checker.py‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7157,9 +7157,7 @@ def narrow_type_by_identity_equality(
71577157
if narrowable_expr_type is None:
71587158
if_type = else_type = ambiguous_expr_type
71597159
else:
7160-
narrowable_expr_type = try_expanding_sum_type_to_union(
7161-
coerce_to_literal(narrowable_expr_type), None
7162-
)
7160+
narrowable_expr_type = coerce_to_literal(narrowable_expr_type)
71637161
if_type, else_type = conditional_types(
71647162
narrowable_expr_type,
71657163
[TypeRange(target_type, is_upper_bound=False)],
@@ -7236,7 +7234,7 @@ def narrow_type_by_identity_equality(
72367234
# we narrow to in the if_map
72377235
or_if_maps.append({operands[i]: expr_type})
72387236

7239-
expr_type = coerce_to_literal(try_expanding_sum_type_to_union(expr_type, None))
7237+
expr_type = coerce_to_literal(expr_type)
72407238
for j in expr_indices:
72417239
if j in custom_eq_indices:
72427240
if i == j:
@@ -7262,9 +7260,6 @@ def narrow_type_by_identity_equality(
72627260
if narrowable_expr_type is None:
72637261
if_type = else_type = ambiguous_expr_type
72647262
else:
7265-
narrowable_expr_type = coerce_to_literal(
7266-
try_expanding_sum_type_to_union(narrowable_expr_type, None)
7267-
)
72687263
if_type, else_type = conditional_types(
72697264
narrowable_expr_type,
72707265
[TypeRange(target_type, is_upper_bound=False)],

‎test-data/unit/check-narrowing.test‎

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ def f2(x: Union[Default, Literal[1], Literal[2]]):
861861

862862
[case testNarrowingEqualityCustomEqualityEnum]
863863
# flags: --strict-equality --warn-unreachable
864-
from typing import Literal, Union
864+
from typing import Literal
865865
from enum import Enum
866866

867867
class CustomEnum(Enum):
@@ -870,18 +870,24 @@ class CustomEnum(Enum):
870870

871871
def __eq__(self, other: object) -> bool: return True
872872

873-
x3: CustomEnum
874-
key: Literal[CustomEnum.A]
875-
if x3 == key:
876-
reveal_type(x3) # N: Revealed type is "__main__.CustomEnum"
877-
else:
878-
reveal_type(x3) # N: Revealed type is "Literal[__main__.CustomEnum.B]"
873+
def check_equality(x: CustomEnum, key: Literal[CustomEnum.A]) -> None:
874+
if x == key:
875+
reveal_type(x) # N: Revealed type is "__main__.CustomEnum"
876+
else:
877+
reveal_type(x) # N: Revealed type is "Literal[__main__.CustomEnum.B]"
879878

880879
# For comparison, this narrows since we bypass __eq__
881-
if x3 is key:
882-
reveal_type(x3) # N: Revealed type is "Literal[__main__.CustomEnum.A]"
883-
else:
884-
reveal_type(x3) # N: Revealed type is "Literal[__main__.CustomEnum.B]"
880+
def check_identity(x: CustomEnum, key: Literal[CustomEnum.A]) -> None:
881+
if x is key:
882+
reveal_type(x) # N: Revealed type is "Literal[__main__.CustomEnum.A]"
883+
else:
884+
reveal_type(x) # N: Revealed type is "Literal[__main__.CustomEnum.B]"
885+
886+
def check_optional_equality(x: CustomEnum | None, key: Literal[CustomEnum.A]) -> None:
887+
if x == key:
888+
reveal_type(x) # N: Revealed type is "__main__.CustomEnum"
889+
else:
890+
reveal_type(x) # N: Revealed type is "Literal[__main__.CustomEnum.B] | None"
885891
[builtins fixtures/primitives.pyi]
886892

887893
[case testNarrowingEqualityCustomEqualityChainedComparison]

0 commit comments

Comments
 (0)