Skip to content

Commit dbea92a

Browse files
committed
Fix value-in-container narrowing widening to non-subtypes (#21512)
When narrowing `x` in `x in container`, mypy used __eq__-based narrowing which could widen `x` to the container's item type even when that type is not a proper subtype of `x`'s declared type. Discard the if-branch narrowing result when it is not a proper subtype of the original type.
1 parent 5e0c274 commit dbea92a

1 file changed

Lines changed: 10 additions & 0 deletions

File tree

mypy/checker.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6831,6 +6831,16 @@ def comparison_type_narrowing_helper(self, node: ComparisonExpr) -> tuple[TypeMa
68316831
# We can't do negative narrowing, since e.g. the container could
68326832
# just be empty.
68336833
else_map = {}
6834+
# The `in` operator uses __eq__, not isinstance. Knowing that
6835+
# value == some_container_element does not imply value has the
6836+
# runtime type of that element. Discard any narrowing that would
6837+
# widen item_type to a non-subtype (e.g. tuple[int,int,int] must
6838+
# not be widened to a subclass Size just because they compare equal).
6839+
left_expr = collapse_walrus(operands[left_index])
6840+
if left_expr in if_map and not is_proper_subtype(
6841+
if_map[left_expr], item_type, ignore_promotions=True
6842+
):
6843+
del if_map[left_expr]
68346844

68356845
if right_index in narrowable_operand_index_to_hash:
68366846
# E.g. narrows the right operand in `if "key" in typed_dict`

0 commit comments

Comments
 (0)