@@ -243,14 +243,8 @@ def accept_loop(self, body: Node, else_body: Node = None, *,
243
243
break
244
244
self .binder .pop_loop_frame ()
245
245
if exit_condition :
246
- _ , else_map = find_isinstance_check (
247
- exit_condition , self .type_map , self .typing_mode_weak ()
248
- )
249
- if else_map is None :
250
- self .binder .unreachable ()
251
- else :
252
- for var , type in else_map .items ():
253
- self .binder .push (var , type )
246
+ _ , else_map = self .find_isinstance_check (exit_condition )
247
+ self .push_type_map (else_map )
254
248
if else_body :
255
249
self .accept (else_body )
256
250
@@ -1441,37 +1435,19 @@ def visit_if_stmt(self, s: IfStmt) -> Type:
1441
1435
for e , b in zip (s .expr , s .body ):
1442
1436
t = self .accept (e )
1443
1437
self .check_not_void (t , e )
1444
- if_map , else_map = find_isinstance_check (
1445
- e , self .type_map ,
1446
- self .typing_mode_weak ()
1447
- )
1448
- if if_map is None :
1449
- # The condition is always false
1450
- # XXX should issue a warning?
1451
- pass
1452
- else :
1453
- # Only type check body if the if condition can be true.
1454
- with self .binder .frame_context (can_skip = True , fall_through = 2 ):
1455
- if if_map :
1456
- for var , type in if_map .items ():
1457
- self .binder .push (var , type )
1458
-
1459
- self .accept (b )
1460
-
1461
- if else_map :
1462
- for var , type in else_map .items ():
1463
- self .binder .push (var , type )
1464
- if else_map is None :
1465
- # The condition is always true => remaining elif/else blocks
1466
- # can never be reached.
1467
-
1468
- # Might also want to issue a warning
1469
- # print("Warning: isinstance always true")
1470
- break
1471
- else : # Didn't break => can't prove one of the conditions is always true
1472
- with self .binder .frame_context (can_skip = False , fall_through = 2 ):
1473
- if s .else_body :
1474
- self .accept (s .else_body )
1438
+ if_map , else_map = self .find_isinstance_check (e )
1439
+
1440
+ # XXX Issue a warning if condition is always False?
1441
+ with self .binder .frame_context (can_skip = True , fall_through = 2 ):
1442
+ self .push_type_map (if_map )
1443
+ self .accept (b )
1444
+
1445
+ # XXX Issue a warning if condition is always True?
1446
+ self .push_type_map (else_map )
1447
+
1448
+ with self .binder .frame_context (can_skip = False , fall_through = 2 ):
1449
+ if s .else_body :
1450
+ self .accept (s .else_body )
1475
1451
return None
1476
1452
1477
1453
def visit_while_stmt (self , s : WhileStmt ) -> Type :
@@ -1497,16 +1473,9 @@ def visit_assert_stmt(self, s: AssertStmt) -> Type:
1497
1473
self .accept (s .expr )
1498
1474
1499
1475
# If this is asserting some isinstance check, bind that type in the following code
1500
- true_map , _ = find_isinstance_check (
1501
- s .expr , self .type_map ,
1502
- self .typing_mode_weak ()
1503
- )
1476
+ true_map , _ = self .find_isinstance_check (s .expr )
1504
1477
1505
- if true_map is None :
1506
- self .binder .unreachable ()
1507
- else :
1508
- for var , type in true_map .items ():
1509
- self .binder .push (var , type )
1478
+ self .push_type_map (true_map )
1510
1479
1511
1480
def visit_raise_stmt (self , s : RaiseStmt ) -> Type :
1512
1481
"""Type check a raise statement."""
@@ -2135,6 +2104,17 @@ def function_type(self, func: FuncBase) -> FunctionLike:
2135
2104
def method_type (self , func : FuncBase ) -> FunctionLike :
2136
2105
return method_type_with_fallback (func , self .named_type ('builtins.function' ))
2137
2106
2107
+ def find_isinstance_check (self , n : Node ) -> Tuple [Optional [Dict [Node , Type ]],
2108
+ Optional [Dict [Node , Type ]]]:
2109
+ return find_isinstance_check (n , self .type_map , self .typing_mode_weak ())
2110
+
2111
+ def push_type_map (self , type_map : Optional [Dict [Node , Type ]]) -> None :
2112
+ if type_map is None :
2113
+ self .binder .unreachable ()
2114
+ else :
2115
+ for expr , type in type_map .items ():
2116
+ self .binder .push (expr , type )
2117
+
2138
2118
2139
2119
# Data structure returned by find_isinstance_check representing
2140
2120
# information learned from the truth or falsehood of a condition. The
0 commit comments