diff --git a/mypy/checker.py b/mypy/checker.py index 64852cb724f4..58b2cbf35e5d 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -6989,16 +6989,6 @@ def comparison_type_narrowing_helper(self, node: ComparisonExpr) -> tuple[TypeMa all_if_maps = [] all_else_maps = [] for known_item in container_item_types: - # Match the should_coerce_literals logic from narrow_type_by_identity_equality - p_known_item = get_proper_type(known_item) - if ( - is_literal_type_like(p_known_item) - or ( - isinstance(p_known_item, Instance) - and p_known_item.type.is_enum - ) - ) and not has_custom_eq_checks(p_known_item): - known_item = coerce_to_literal(known_item) if_map, else_map = self.narrow_type_by_identity_equality( "==", operands=[operands[left_index], operands[right_index]], @@ -7007,8 +6997,7 @@ def comparison_type_narrowing_helper(self, node: ComparisonExpr) -> tuple[TypeMa narrowable_indices={0}, ) all_if_maps.append(if_map) - if is_singleton_equality_type(get_proper_type(known_item)): - all_else_maps.append(else_map) + all_else_maps.append(else_map) if_map = reduce_or_conditional_type_maps(all_if_maps) else_map = reduce_and_conditional_type_maps(all_else_maps, use_meet=True) else: diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index 1ee146be86f0..5389f4143c27 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -2670,6 +2670,7 @@ def f(x: str | int) -> None: [case testConsistentNarrowingEqAndInWithCustomEq] # flags: --strict-equality --warn-unreachable +from typing import Literal # https://github.com/python/mypy/issues/17864 class C: @@ -2689,14 +2690,30 @@ class D(C): def f1(x: C) -> None: if x in [D(5)]: reveal_type(x) # D # N: Revealed type is "__main__.C" + else: + reveal_type(x) # N: Revealed type is "__main__.C" f1(C(5)) def f2(x: C) -> None: if x == D(5): reveal_type(x) # D # N: Revealed type is "__main__.C" + else: + reveal_type(x) # N: Revealed type is "__main__.C" f2(C(5)) + +def f3(x: C | Literal[1, 2, 3]) -> None: + if x not in (1, 2): + reveal_type(x) # N: Revealed type is "__main__.C | Literal[3]" + else: + reveal_type(x) # N: Revealed type is "__main__.C | Literal[1] | Literal[2]" + +def f4(x: Literal[1, 2], y: C | Literal[1]) -> None: + if x in [y]: + reveal_type(x) # N: Revealed type is "Literal[1] | Literal[2]" + else: + reveal_type(x) # N: Revealed type is "Literal[1] | Literal[2]" [builtins fixtures/primitives.pyi] [case testNarrowingTypeVarNone] @@ -3251,14 +3268,13 @@ def narrow_tuple_exact(x: Literal['a', 'b', 'c'], t: tuple[Literal['a'], Literal reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']" def narrow_tuple_expression(x: Literal['a', 'b', 'c']): - # TODO: this should match narrow_tuple_exact if x in ('a', 'b'): reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']" else: - reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" + reveal_type(x) # N: Revealed type is "Literal['c']" if x not in ('a', 'b'): - reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" + reveal_type(x) # N: Revealed type is "Literal['c']" else: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']" @@ -3294,7 +3310,7 @@ def narrow_list(x: Literal['a', 'b', 'c'], t: list[Literal['a', 'b']]): if x in ['a', 'b']: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']" else: - reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" + reveal_type(x) # N: Revealed type is "Literal['c']" if x in ['a', 'b', *[]]: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" @@ -3310,7 +3326,7 @@ def narrow_set(x: Literal['a', 'b', 'c'], t: set[Literal['a', 'b']]): if x in {'a', 'b'}: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']" else: - reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" + reveal_type(x) # N: Revealed type is "Literal['c']" if x in {'a', 'b', *[]}: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" @@ -3326,7 +3342,7 @@ def narrow_dict(x: Literal['a', 'b', 'c'], t: dict[Literal['a', 'b'], int]): if x in {'a': 0, 'b': 1}: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b']" else: - reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" + reveal_type(x) # N: Revealed type is "Literal['c']" if x in {'a': 0, 'b': 1, **{}}: reveal_type(x) # N: Revealed type is "Literal['a'] | Literal['b'] | Literal['c']" @@ -3350,6 +3366,8 @@ class E(Enum): def f(x: int) -> None: if x in [E.foo, E.bar]: reveal_type(x) # N: Revealed type is "builtins.int" + else: + reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/list.pyi]