@@ -533,6 +533,69 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
533
533
}
534
534
}
535
535
536
+ fn check_iscleanup ( & mut self , mir : & Mir < ' tcx > , block : & BasicBlockData < ' tcx > )
537
+ {
538
+ let is_cleanup = block. is_cleanup ;
539
+ self . last_span = block. terminator ( ) . span ;
540
+ match block. terminator ( ) . kind {
541
+ TerminatorKind :: Goto { target } =>
542
+ self . assert_iscleanup ( mir, block, target, is_cleanup) ,
543
+ TerminatorKind :: If { targets : ( on_true, on_false) , .. } => {
544
+ self . assert_iscleanup ( mir, block, on_true, is_cleanup) ;
545
+ self . assert_iscleanup ( mir, block, on_false, is_cleanup) ;
546
+ }
547
+ TerminatorKind :: Switch { ref targets, .. } |
548
+ TerminatorKind :: SwitchInt { ref targets, .. } => {
549
+ for target in targets {
550
+ self . assert_iscleanup ( mir, block, * target, is_cleanup) ;
551
+ }
552
+ }
553
+ TerminatorKind :: Resume => {
554
+ if !is_cleanup {
555
+ span_mirbug ! ( self , block, "resume on non-cleanup block!" )
556
+ }
557
+ }
558
+ TerminatorKind :: Return => {
559
+ if is_cleanup {
560
+ span_mirbug ! ( self , block, "return on cleanup block" )
561
+ }
562
+ }
563
+ TerminatorKind :: Drop { target, unwind, .. } |
564
+ TerminatorKind :: DropAndReplace { target, unwind, .. } => {
565
+ self . assert_iscleanup ( mir, block, target, is_cleanup) ;
566
+ if let Some ( unwind) = unwind {
567
+ if is_cleanup {
568
+ span_mirbug ! ( self , block, "unwind on cleanup block" )
569
+ }
570
+ self . assert_iscleanup ( mir, block, unwind, true ) ;
571
+ }
572
+ }
573
+ TerminatorKind :: Call { ref destination, cleanup, .. } => {
574
+ if let & Some ( ( _, target) ) = destination {
575
+ self . assert_iscleanup ( mir, block, target, is_cleanup) ;
576
+ }
577
+ if let Some ( cleanup) = cleanup {
578
+ if is_cleanup {
579
+ span_mirbug ! ( self , block, "cleanup on cleanup block" )
580
+ }
581
+ self . assert_iscleanup ( mir, block, cleanup, true ) ;
582
+ }
583
+ }
584
+ }
585
+ }
586
+
587
+ fn assert_iscleanup ( & mut self ,
588
+ mir : & Mir < ' tcx > ,
589
+ ctxt : & fmt:: Debug ,
590
+ bb : BasicBlock ,
591
+ iscleanuppad : bool )
592
+ {
593
+ if mir. basic_block_data ( bb) . is_cleanup != iscleanuppad {
594
+ span_mirbug ! ( self , ctxt, "cleanuppad mismatch: {:?} should be {:?}" ,
595
+ bb, iscleanuppad) ;
596
+ }
597
+ }
598
+
536
599
fn typeck_mir ( & mut self , mir : & Mir < ' tcx > ) {
537
600
self . last_span = mir. span ;
538
601
debug ! ( "run_on_mir: {:?}" , mir. span) ;
@@ -544,9 +607,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
544
607
self . check_stmt ( mir, stmt) ;
545
608
}
546
609
547
- if let Some ( ref terminator) = block. terminator {
548
- self . check_terminator ( mir, terminator) ;
549
- }
610
+ self . check_terminator ( mir, block. terminator ( ) ) ;
611
+ self . check_iscleanup ( mir, block) ;
550
612
}
551
613
}
552
614
0 commit comments