Skip to content

Commit 6acba65

Browse files
committed
check for is_cleanup violations in MIR typeck
There weren't any in practice, but as these cause MSVC-only problems, the check looks like a good idea.
1 parent f993148 commit 6acba65

File tree

1 file changed

+65
-3
lines changed

1 file changed

+65
-3
lines changed

src/librustc_mir/transform/type_check.rs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,69 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
555555
}
556556
}
557557

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+
558621
fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
559622
self.last_span = mir.span;
560623
debug!("run_on_mir: {:?}", mir.span);
@@ -566,9 +629,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
566629
self.check_stmt(mir, stmt);
567630
}
568631

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);
572634
}
573635
}
574636

0 commit comments

Comments
 (0)