@@ -584,24 +584,44 @@ def accept_loop(
584
584
* ,
585
585
exit_condition : Expression | None = None ,
586
586
) -> None :
587
- """Repeatedly type check a loop body until the frame doesn't change.
588
- If exit_condition is set, assume it must be False on exit from the loop.
587
+ """Repeatedly type check a loop body until the frame doesn't change."""
589
588
590
- Then check the else_body.
591
- """
592
- # The outer frame accumulates the results of all iterations
589
+ # The outer frame accumulates the results of all iterations:
593
590
with self .binder .frame_context (can_skip = False , conditional_frame = True ):
591
+
592
+ # Check for potential decreases in the number of partial types so as not to stop the
593
+ # iteration too early:
594
594
partials_old = sum (len (pts .map ) for pts in self .partial_types )
595
+
596
+ # Disable error types that we cannot safely identify in intermediate iteration steps:
597
+ warn_unreachable = self .options .warn_unreachable
598
+ if warn_unreachable :
599
+ self .options .warn_unreachable = False
600
+ warn_redundant = codes .REDUNDANT_EXPR in self .options .enabled_error_codes
601
+ if warn_redundant :
602
+ self .options .enabled_error_codes .remove (codes .REDUNDANT_EXPR )
603
+
595
604
while True :
596
605
with self .binder .frame_context (can_skip = True , break_frame = 2 , continue_frame = 1 ):
597
606
self .accept (body )
598
607
partials_new = sum (len (pts .map ) for pts in self .partial_types )
599
608
if (partials_new == partials_old ) and not self .binder .last_pop_changed :
600
609
break
601
610
partials_old = partials_new
611
+
612
+ # If necessary, reset the modified options and make up for the postponed error checks:
613
+ if warn_unreachable or warn_redundant :
614
+ self .options .warn_unreachable = warn_unreachable
615
+ self .options .enabled_error_codes .add (codes .REDUNDANT_EXPR )
616
+ with self .binder .frame_context (can_skip = True , break_frame = 2 , continue_frame = 1 ):
617
+ self .accept (body )
618
+
619
+ # If exit_condition is set, assume it must be False on exit from the loop:
602
620
if exit_condition :
603
621
_ , else_map = self .find_isinstance_check (exit_condition )
604
622
self .push_type_map (else_map )
623
+
624
+ # Check the else body:
605
625
if else_body :
606
626
self .accept (else_body )
607
627
0 commit comments