diff --git a/mypy/checker.py b/mypy/checker.py index 7d0b5dbde09d..5c9bc5fe5863 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -6674,8 +6674,8 @@ def comparison_type_narrowing_helper(self, node: ComparisonExpr) -> tuple[TypeMa # If we have found non-trivial restrictions from the regular comparisons, # then return soon. Otherwise try to infer restrictions involving `len(x)`. # TODO: support regular and len() narrowing in the same chain. - if any(m != ({}, {}) for m in partial_type_maps): - return reduce_conditional_maps(partial_type_maps) + if any(len(m[0]) or len(m[1]) for m in partial_type_maps): + return reduce_conditional_maps(partial_type_maps, use_meet=True) else: # Use meet for `and` maps to get correct results for chained checks # like `if 1 < len(x) < 4: ...` diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index 93a720728876..0608d2a0b2f1 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -3264,6 +3264,39 @@ def bad_but_should_pass(has_key: bool, key: bool, s: tuple[bool, ...]) -> None: reveal_type(key) # N: Revealed type is "builtins.bool" [builtins fixtures/primitives.pyi] +[case testNarrowChainedComparisonMeet] +# flags: --strict-equality --warn-unreachable +from __future__ import annotations +from typing import Any + +def f1(a: str | None, b: str | None) -> None: + if None is not a == b: + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(b) # N: Revealed type is "builtins.str | None" + + if (None is not a) and (a == b): + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(b) # N: Revealed type is "builtins.str" + +def f2(a: Any | None, b: str | None) -> None: + if None is not a == b: + reveal_type(a) # N: Revealed type is "Any" + reveal_type(b) # N: Revealed type is "builtins.str | None" + + if (None is not a) and (a == b): + reveal_type(a) # N: Revealed type is "Any" + reveal_type(b) # N: Revealed type is "builtins.str | None" + +def f3(a: str | None, b: Any | None) -> None: + if None is not a == b: + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(b) # N: Revealed type is "Any | builtins.str | None" + + if (None is not a) and (a == b): + reveal_type(a) # N: Revealed type is "builtins.str" + reveal_type(b) # N: Revealed type is "Any | builtins.str" +[builtins fixtures/primitives.pyi] + [case testNarrowTypeObject] # flags: --strict-equality --warn-unreachable from typing import Any