Skip to content

Commit b778ff0

Browse files
committed
fixed Incorrect type of enum in 'if' clause #20234
1 parent 8e2ce96 commit b778ff0

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

mypy/checker.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@
241241
from mypy.typevars import fill_typevars, fill_typevars_with_any, has_no_typevars
242242
from mypy.util import is_dunder, is_sunder
243243
from mypy.visitor import NodeVisitor
244+
from mypy.types import LiteralType
244245

245246
T = TypeVar("T")
246247

@@ -6517,7 +6518,6 @@ def comparison_type_narrowing_helper(self, node: ComparisonExpr) -> tuple[TypeMa
65176518
# Step 1: Obtain the types of each operand and whether or not we can
65186519
# narrow their types. (For example, we shouldn't try narrowing the
65196520
# types of literal string or enum expressions).
6520-
65216521
operands = [collapse_walrus(x) for x in node.operands]
65226522
operand_types = []
65236523
narrowable_operand_index_to_hash = {}
@@ -6581,18 +6581,39 @@ def comparison_type_narrowing_helper(self, node: ComparisonExpr) -> tuple[TypeMa
65816581

65826582
if left_index in narrowable_operand_index_to_hash:
65836583
# We only try and narrow away 'None' for now
6584-
if is_overlapping_none(item_type):
6585-
collection_item_type = get_proper_type(builtin_item_type(iterable_type))
6586-
if (
6587-
collection_item_type is not None
6588-
and not is_overlapping_none(collection_item_type)
6589-
and not (
6590-
isinstance(collection_item_type, Instance)
6591-
and collection_item_type.type.fullname == "builtins.object"
6592-
)
6593-
and is_overlapping_erased_types(item_type, collection_item_type)
6594-
):
6595-
if_map[operands[left_index]] = remove_optional(item_type)
6584+
if is_overlapping_none(item_type):
6585+
collection_item_type = get_proper_type(builtin_item_type(iterable_type))
6586+
if (
6587+
collection_item_type is not None
6588+
and not is_overlapping_none(collection_item_type)
6589+
and not (
6590+
isinstance(collection_item_type, Instance)
6591+
and collection_item_type.type.fullname == "builtins.object"
6592+
)
6593+
and is_overlapping_erased_types(item_type, collection_item_type)
6594+
):
6595+
if_map[operands[left_index]] = remove_optional(item_type)
6596+
if_map[operands[left_index]] = remove_optional(item_type)
6597+
literal_types = []
6598+
if isinstance(get_proper_type(iterable_type), TupleType):
6599+
# Check if this is an enum instance that can be narrowed
6600+
tuple_type = get_proper_type(iterable_type)
6601+
for i, item_type in enumerate(tuple_type.items):
6602+
if isinstance(item_type, Instance):
6603+
6604+
if item_type.type.is_enum:
6605+
# Enum values in tuples are represented as Instance types, not LiteralType
6606+
if hasattr(item_type, 'last_known_value') and item_type.last_known_value:
6607+
# Use the existing literal representation
6608+
literal_types.append(item_type.last_known_value)
6609+
else:
6610+
# using the instance directly
6611+
literal_types.append(item_type)
6612+
# If we found enum literals in the tuple, narrow the left operand
6613+
if literal_types:
6614+
union_type = make_simplified_union(literal_types)
6615+
# Applying type narrowing for the true branch of the 'in' check
6616+
if_map[operands[left_index]] = union_type
65966617

65976618
if right_index in narrowable_operand_index_to_hash:
65986619
if_type, else_type = self.conditional_types_for_iterable(

0 commit comments

Comments
 (0)