@@ -584,24 +584,43 @@ 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
+ warn_redundant = codes .REDUNDANT_EXPR in self .options .enabled_error_codes
599
+ self .options .warn_unreachable = False
600
+ self .options .enabled_error_codes .discard (codes .REDUNDANT_EXPR )
601
+
595
602
while True :
596
603
with self .binder .frame_context (can_skip = True , break_frame = 2 , continue_frame = 1 ):
597
604
self .accept (body )
598
605
partials_new = sum (len (pts .map ) for pts in self .partial_types )
599
606
if (partials_new == partials_old ) and not self .binder .last_pop_changed :
600
607
break
601
608
partials_old = partials_new
609
+
610
+ # If necessary, reset the modified options and make up for the postponed error checks:
611
+ self .options .warn_unreachable = warn_unreachable
612
+ if warn_redundant :
613
+ self .options .enabled_error_codes .add (codes .REDUNDANT_EXPR )
614
+ if warn_unreachable or warn_redundant :
615
+ with self .binder .frame_context (can_skip = True , break_frame = 2 , continue_frame = 1 ):
616
+ self .accept (body )
617
+
618
+ # If exit_condition is set, assume it must be False on exit from the loop:
602
619
if exit_condition :
603
620
_ , else_map = self .find_isinstance_check (exit_condition )
604
621
self .push_type_map (else_map )
622
+
623
+ # Check the else body:
605
624
if else_body :
606
625
self .accept (else_body )
607
626
0 commit comments