Skip to content

Commit 148f842

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 f6068ea commit 148f842

File tree

1 file changed

+65
-3
lines changed

1 file changed

+65
-3
lines changed

src/librustc_mir/transform/type_check.rs

+65-3
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)