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,44 @@ 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 )
1422
-
1423
- if_type = self .accept (e .if_expr )
1424
-
1425
- self .chk .binder .pop_frame ()
1426
- self .chk .binder .push_frame ()
1427
-
1428
- if else_map :
1429
- for var , type in else_map .items ():
1430
- self .chk .binder .push (var , type )
1418
+ with self .chk .binder :
1419
+ if if_map :
1420
+ for var , type in if_map .items ():
1421
+ self .chk .binder .push (var , type )
1422
+ if_type = self .accept (e .if_expr , context = ctx )
1423
+
1424
+ if has_unfinished_types (if_type ):
1425
+ # Analyze the right branch disregarding the left branch.
1426
+ with self .chk .binder :
1427
+ if else_map :
1428
+ for var , type in else_map .items ():
1429
+ self .chk .binder .push (var , type )
1430
+ else_type = self .accept (e .else_expr , context = ctx )
1431
+
1432
+ # If it would make a difference, re-analyze the left
1433
+ # branch using the right branch's type as context.
1434
+ if ctx is None or not is_equivalent (else_type , ctx ):
1435
+ # TODO: If it's possible that the previous analysis of
1436
+ # the left branch produced errors that are avoided
1437
+ # using this context, suppress those errors.
1438
+ with self .chk .binder :
1439
+ if if_map :
1440
+ for var , type in if_map .items ():
1441
+ self .chk .binder .push (var , type )
1442
+ if_type = self .accept (e .if_expr , context = else_type )
1431
1443
1432
- else_type = self .accept (e .else_expr , context = if_type )
1444
+ else :
1445
+ # Analyze the right branch in the context of the left
1446
+ # branch's type.
1447
+ with self .chk .binder :
1448
+ if else_map :
1449
+ for var , type in else_map .items ():
1450
+ self .chk .binder .push (var , type )
1451
+ else_type = self .accept (e .else_expr , context = if_type )
1433
1452
1434
- self . chk . binder . pop_frame ( )
1453
+ res = join . join_types ( if_type , else_type )
1435
1454
1436
- return join . join_types ( if_type , else_type )
1455
+ return res
1437
1456
1438
1457
def visit_backquote_expr (self , e : BackquoteExpr ) -> Type :
1439
1458
self .accept (e .expr )
@@ -1505,6 +1524,19 @@ def not_ready_callback(self, name: str, context: Context) -> None:
1505
1524
self .chk .handle_cannot_determine_type (name , context )
1506
1525
1507
1526
1527
+ # TODO: What's a good name for this function?
1528
+ def has_unfinished_types (t : Type ) -> bool :
1529
+ """Check whether t has type variables replaced with 'None'.
1530
+
1531
+ This can happen when `[]` is evaluated without sufficient context.
1532
+ """
1533
+ if isinstance (t , NoneTyp ):
1534
+ return True
1535
+ if isinstance (t , Instance ):
1536
+ return any (has_unfinished_types (arg ) for arg in t .args )
1537
+ return False
1538
+
1539
+
1508
1540
def map_actuals_to_formals (caller_kinds : List [int ],
1509
1541
caller_names : List [str ],
1510
1542
callee_kinds : List [int ],
0 commit comments