@@ -555,6 +555,69 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
555
555
}
556
556
}
557
557
558
+ fn check_iscleanup ( & mut self , mir : & Mir < ' tcx > , block : & BasicBlockData < ' tcx > )
559
+ {
560
+ let is_cleanup = block. is_cleanup ;
561
+ self . last_span = block. terminator ( ) . span ;
562
+ match block. terminator ( ) . kind {
563
+ TerminatorKind :: Goto { target } =>
564
+ self . assert_iscleanup ( mir, block, target, is_cleanup) ,
565
+ TerminatorKind :: If { targets : ( on_true, on_false) , .. } => {
566
+ self . assert_iscleanup ( mir, block, on_true, is_cleanup) ;
567
+ self . assert_iscleanup ( mir, block, on_false, is_cleanup) ;
568
+ }
569
+ TerminatorKind :: Switch { ref targets, .. } |
570
+ TerminatorKind :: SwitchInt { ref targets, .. } => {
571
+ for target in targets {
572
+ self . assert_iscleanup ( mir, block, * target, is_cleanup) ;
573
+ }
574
+ }
575
+ TerminatorKind :: Resume => {
576
+ if !is_cleanup {
577
+ span_mirbug ! ( self , block, "resume on non-cleanup block!" )
578
+ }
579
+ }
580
+ TerminatorKind :: Return => {
581
+ if is_cleanup {
582
+ span_mirbug ! ( self , block, "return on cleanup block" )
583
+ }
584
+ }
585
+ TerminatorKind :: Drop { target, unwind, .. } |
586
+ TerminatorKind :: DropAndReplace { target, unwind, .. } => {
587
+ self . assert_iscleanup ( mir, block, target, is_cleanup) ;
588
+ if let Some ( unwind) = unwind {
589
+ if is_cleanup {
590
+ span_mirbug ! ( self , block, "unwind on cleanup block" )
591
+ }
592
+ self . assert_iscleanup ( mir, block, unwind, true ) ;
593
+ }
594
+ }
595
+ TerminatorKind :: Call { ref destination, cleanup, .. } => {
596
+ if let & Some ( ( _, target) ) = destination {
597
+ self . assert_iscleanup ( mir, block, target, is_cleanup) ;
598
+ }
599
+ if let Some ( cleanup) = cleanup {
600
+ if is_cleanup {
601
+ span_mirbug ! ( self , block, "cleanup on cleanup block" )
602
+ }
603
+ self . assert_iscleanup ( mir, block, cleanup, true ) ;
604
+ }
605
+ }
606
+ }
607
+ }
608
+
609
+ fn assert_iscleanup ( & mut self ,
610
+ mir : & Mir < ' tcx > ,
611
+ ctxt : & fmt:: Debug ,
612
+ bb : BasicBlock ,
613
+ iscleanuppad : bool )
614
+ {
615
+ if mir. basic_block_data ( bb) . is_cleanup != iscleanuppad {
616
+ span_mirbug ! ( self , ctxt, "cleanuppad mismatch: {:?} should be {:?}" ,
617
+ bb, iscleanuppad) ;
618
+ }
619
+ }
620
+
558
621
fn typeck_mir ( & mut self , mir : & Mir < ' tcx > ) {
559
622
self . last_span = mir. span ;
560
623
debug ! ( "run_on_mir: {:?}" , mir. span) ;
@@ -566,9 +629,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
566
629
self . check_stmt ( mir, stmt) ;
567
630
}
568
631
569
- if let Some ( ref terminator) = block. terminator {
570
- self . check_terminator ( mir, terminator) ;
571
- }
632
+ self . check_terminator ( mir, block. terminator ( ) ) ;
633
+ self . check_iscleanup ( mir, block) ;
572
634
}
573
635
}
574
636
0 commit comments