diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index edc3ac70fa54..4ca55e1679e4 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -4288,7 +4288,9 @@ def check_boolean_op(self, e: OpExpr, context: Context) -> Type: ): self.msg.unreachable_right_operand(e.op, e.right) - right_type = self.analyze_cond_branch(right_map, e.right, expanded_left_type) + right_type = self.analyze_cond_branch( + right_map, e.right, self._combined_context(expanded_left_type) + ) if left_map is None and right_map is None: return UninhabitedType() @@ -5919,6 +5921,16 @@ def analyze_cond_branch( self.chk.push_type_map(map) return self.accept(node, type_context=context, allow_none_return=allow_none_return) + def _combined_context(self, ty: Type | None) -> Type | None: + ctx_items = [] + if ty is not None: + ctx_items.append(ty) + if self.type_context and self.type_context[-1] is not None: + ctx_items.append(self.type_context[-1]) + if ctx_items: + return make_simplified_union(ctx_items) + return None + # # Helpers # diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index 0aa67b2bf7f3..67ae22a369b1 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -1510,3 +1510,24 @@ def mymin( def check(paths: Iterable[str], key: Callable[[str], int]) -> Union[str, None]: return mymin(paths, key=key, default=None) [builtins fixtures/tuple.pyi] + +[case testBinaryOpInferenceContext] +from typing import Literal, TypeVar + +T = TypeVar("T") + +def identity(x: T) -> T: + return x + +def check1(use: bool, val: str) -> "str | Literal[True]": + return use or identity(val) + +def check2(use: bool, val: str) -> "str | bool": + return use or identity(val) + +def check3(use: bool, val: str) -> "str | Literal[False]": + return use and identity(val) + +def check4(use: bool, val: str) -> "str | bool": + return use and identity(val) +[builtins fixtures/tuple.pyi]