11"""Expression type checker. This file is conceptually part of TypeChecker."""
22
3- from typing import cast , List , Tuple , Callable , Union , Optional
3+ from typing import cast , Dict , List , Tuple , Callable , Union , Optional
44
55from mypy .types import (
66 Type , AnyType , CallableType , Overloaded , NoneTyp , Void , TypeVarDef ,
2727from mypy import messages
2828from mypy .infer import infer_type_arguments , infer_function_type_arguments
2929from mypy import join
30- from mypy .subtypes import is_subtype
30+ from mypy .subtypes import is_subtype , is_equivalent
3131from mypy import applytype
3232from mypy import erasetype
3333from mypy .checkmember import analyze_member_access , type_object_type
@@ -1406,6 +1406,7 @@ def check_for_comp(self, e: Union[GeneratorExpr, DictionaryComprehension]) -> No
14061406 def visit_conditional_expr (self , e : ConditionalExpr ) -> Type :
14071407 cond_type = self .accept (e .cond )
14081408 self .check_not_void (cond_type , e )
1409+ ctx = self .chk .type_context [- 1 ]
14091410
14101411 # Gain type information from isinstance if it is there
14111412 # but only for the current expression
@@ -1414,26 +1415,36 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type:
14141415 self .chk .type_map ,
14151416 self .chk .typing_mode_weak ())
14161417
1417- self .chk .binder .push_frame ()
1418-
1419- if if_map :
1420- for var , type in if_map .items ():
1421- self .chk .binder .push (var , type )
1418+ if_type = self .analyze_cond_branch (if_map , e .if_expr , context = ctx )
14221419
1423- if_type = self .accept (e .if_expr )
1420+ if not mypy .checker .is_valid_inferred_type (if_type ):
1421+ # Analyze the right branch disregarding the left branch.
1422+ else_type = self .analyze_cond_branch (else_map , e .else_expr , context = ctx )
14241423
1425- self .chk .binder .pop_frame ()
1426- self .chk .binder .push_frame ()
1424+ # If it would make a difference, re-analyze the left
1425+ # branch using the right branch's type as context.
1426+ if ctx is None or not is_equivalent (else_type , ctx ):
1427+ # TODO: If it's possible that the previous analysis of
1428+ # the left branch produced errors that are avoided
1429+ # using this context, suppress those errors.
1430+ if_type = self .analyze_cond_branch (if_map , e .if_expr , context = else_type )
14271431
1428- if else_map :
1429- for var , type in else_map .items ():
1430- self .chk .binder .push (var , type )
1432+ else :
1433+ # Analyze the right branch in the context of the left
1434+ # branch's type.
1435+ else_type = self .analyze_cond_branch (else_map , e .else_expr , context = if_type )
14311436
1432- else_type = self . accept ( e . else_expr , context = if_type )
1437+ res = join . join_types ( if_type , else_type )
14331438
1434- self . chk . binder . pop_frame ()
1439+ return res
14351440
1436- return join .join_types (if_type , else_type )
1441+ def analyze_cond_branch (self , map : Optional [Dict [Node , Type ]],
1442+ node : Node , context : Optional [Type ]) -> Type :
1443+ with self .chk .binder :
1444+ if map :
1445+ for var , type in map .items ():
1446+ self .chk .binder .push (var , type )
1447+ return self .accept (node , context = context )
14371448
14381449 def visit_backquote_expr (self , e : BackquoteExpr ) -> Type :
14391450 self .accept (e .expr )
0 commit comments