@@ -533,6 +533,69 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
533533 }
534534 }
535535
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+
536599 fn typeck_mir ( & mut self , mir : & Mir < ' tcx > ) {
537600 self . last_span = mir. span ;
538601 debug ! ( "run_on_mir: {:?}" , mir. span) ;
@@ -544,9 +607,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
544607 self . check_stmt ( mir, stmt) ;
545608 }
546609
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) ;
550612 }
551613 }
552614
0 commit comments