1
1
"""Expression type checker. This file is conceptually part of TypeChecker."""
2
2
3
- from typing import cast , List , Tuple , Callable , Union , Optional
3
+ from typing import cast , Dict , List , Tuple , Callable , Union , Optional
4
4
5
5
from mypy .types import (
6
6
Type , AnyType , CallableType , Overloaded , NoneTyp , Void , TypeVarDef ,
27
27
from mypy import messages
28
28
from mypy .infer import infer_type_arguments , infer_function_type_arguments
29
29
from mypy import join
30
- from mypy .subtypes import is_subtype
30
+ from mypy .subtypes import is_subtype , is_equivalent
31
31
from mypy import applytype
32
32
from mypy import erasetype
33
33
from mypy .checkmember import analyze_member_access , type_object_type
@@ -1406,6 +1406,7 @@ def check_for_comp(self, e: Union[GeneratorExpr, DictionaryComprehension]) -> No
1406
1406
def visit_conditional_expr (self , e : ConditionalExpr ) -> Type :
1407
1407
cond_type = self .accept (e .cond )
1408
1408
self .check_not_void (cond_type , e )
1409
+ ctx = self .chk .type_context [- 1 ]
1409
1410
1410
1411
# Gain type information from isinstance if it is there
1411
1412
# but only for the current expression
@@ -1414,26 +1415,36 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type:
1414
1415
self .chk .type_map ,
1415
1416
self .chk .typing_mode_weak ())
1416
1417
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 )
1422
1419
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 )
1424
1423
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 )
1427
1431
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 )
1431
1436
1432
- else_type = self . accept ( e . else_expr , context = if_type )
1437
+ res = join . join_types ( if_type , else_type )
1433
1438
1434
- self . chk . binder . pop_frame ()
1439
+ return res
1435
1440
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 )
1437
1448
1438
1449
def visit_backquote_expr (self , e : BackquoteExpr ) -> Type :
1439
1450
self .accept (e .expr )
0 commit comments