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
@@ -1403,6 +1403,7 @@ def check_for_comp(self, e: Union[GeneratorExpr, DictionaryComprehension]) -> No
1403
1403
def visit_conditional_expr (self , e : ConditionalExpr ) -> Type :
1404
1404
cond_type = self .accept (e .cond )
1405
1405
self .check_not_void (cond_type , e )
1406
+ ctx = self .chk .type_context [- 1 ]
1406
1407
1407
1408
# Gain type information from isinstance if it is there
1408
1409
# but only for the current expression
@@ -1411,26 +1412,44 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type:
1411
1412
self .chk .type_map ,
1412
1413
self .chk .typing_mode_weak ())
1413
1414
1414
- self .chk .binder .push_frame ()
1415
-
1416
- if if_map :
1417
- for var , type in if_map .items ():
1418
- self .chk .binder .push (var , type )
1419
-
1420
- if_type = self .accept (e .if_expr )
1421
-
1422
- self .chk .binder .pop_frame ()
1423
- self .chk .binder .push_frame ()
1424
-
1425
- if else_map :
1426
- for var , type in else_map .items ():
1427
- self .chk .binder .push (var , type )
1415
+ with self .chk .binder :
1416
+ if if_map :
1417
+ for var , type in if_map .items ():
1418
+ self .chk .binder .push (var , type )
1419
+ if_type = self .accept (e .if_expr , context = ctx )
1420
+
1421
+ if has_unfinished_types (if_type ):
1422
+ # Analyze the right branch disregarding the left branch.
1423
+ with self .chk .binder :
1424
+ if else_map :
1425
+ for var , type in else_map .items ():
1426
+ self .chk .binder .push (var , type )
1427
+ else_type = self .accept (e .else_expr , context = ctx )
1428
+
1429
+ # If it would make a difference, re-analyze the left
1430
+ # branch using the right branch's type as context.
1431
+ if ctx is None or not is_equivalent (else_type , ctx ):
1432
+ # TODO: If it's possible that the previous analysis of
1433
+ # the left branch produced errors that are avoided
1434
+ # using this context, suppress those errors.
1435
+ with self .chk .binder :
1436
+ if if_map :
1437
+ for var , type in if_map .items ():
1438
+ self .chk .binder .push (var , type )
1439
+ if_type = self .accept (e .if_expr , context = else_type )
1428
1440
1429
- else_type = self .accept (e .else_expr , context = if_type )
1441
+ else :
1442
+ # Analyze the right branch in the context of the left
1443
+ # branch's type.
1444
+ with self .chk .binder :
1445
+ if else_map :
1446
+ for var , type in else_map .items ():
1447
+ self .chk .binder .push (var , type )
1448
+ else_type = self .accept (e .else_expr , context = if_type )
1430
1449
1431
- self . chk . binder . pop_frame ( )
1450
+ res = join . join_types ( if_type , else_type )
1432
1451
1433
- return join . join_types ( if_type , else_type )
1452
+ return res
1434
1453
1435
1454
def visit_backquote_expr (self , e : BackquoteExpr ) -> Type :
1436
1455
self .accept (e .expr )
@@ -1502,6 +1521,19 @@ def not_ready_callback(self, name: str, context: Context) -> None:
1502
1521
self .chk .handle_cannot_determine_type (name , context )
1503
1522
1504
1523
1524
+ # TODO: What's a good name for this function?
1525
+ def has_unfinished_types (t : Type ) -> bool :
1526
+ """Check whether t has type variables replaced with 'None'.
1527
+
1528
+ This can happen when `[]` is evaluated without sufficient context.
1529
+ """
1530
+ if isinstance (t , NoneTyp ):
1531
+ return True
1532
+ if isinstance (t , Instance ):
1533
+ return any (has_unfinished_types (arg ) for arg in t .args )
1534
+ return False
1535
+
1536
+
1505
1537
def map_actuals_to_formals (caller_kinds : List [int ],
1506
1538
caller_names : List [str ],
1507
1539
callee_kinds : List [int ],
0 commit comments