Strengthen cleanup to cleanup check

This commit is contained in:
Nathan Corbyn 2020-06-08 16:04:41 +01:00
parent 4158bb0f0b
commit 1c4fd22618

View File

@ -13,7 +13,7 @@ use rustc_span::def_id::DefId;
enum EdgeKind { enum EdgeKind {
Unwind, Unwind,
Other, Normal,
} }
pub struct Validator { pub struct Validator {
@ -59,11 +59,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let src = self.body.basic_blocks().get(location.block).unwrap(); let src = self.body.basic_blocks().get(location.block).unwrap();
match (src.is_cleanup, bb.is_cleanup, edge_kind) { match (src.is_cleanup, bb.is_cleanup, edge_kind) {
// Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges // Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges
(false, false, EdgeKind::Other) (false, false, EdgeKind::Normal)
// Non-cleanup blocks can jump to cleanup blocks along unwind edges // Non-cleanup blocks can jump to cleanup blocks along unwind edges
| (false, true, EdgeKind::Unwind) | (false, true, EdgeKind::Unwind)
// Cleanup blocks can jump to cleanup blocks along any edges // Cleanup blocks can jump to cleanup blocks along non-unwind edges
| (true, true, _) => {} | (true, true, EdgeKind::Normal) => {}
// All other jumps are invalid // All other jumps are invalid
_ => { _ => {
self.fail( self.fail(
@ -114,7 +114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
match &terminator.kind { match &terminator.kind {
TerminatorKind::Goto { target } => { TerminatorKind::Goto { target } => {
self.check_bb(location, *target, EdgeKind::Other); self.check_bb(location, *target, EdgeKind::Normal);
} }
TerminatorKind::SwitchInt { targets, values, .. } => { TerminatorKind::SwitchInt { targets, values, .. } => {
if targets.len() != values.len() + 1 { if targets.len() != values.len() + 1 {
@ -128,17 +128,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
); );
} }
for target in targets { for target in targets {
self.check_bb(location, *target, EdgeKind::Other); self.check_bb(location, *target, EdgeKind::Normal);
} }
} }
TerminatorKind::Drop { target, unwind, .. } => { TerminatorKind::Drop { target, unwind, .. } => {
self.check_bb(location, *target, EdgeKind::Other); self.check_bb(location, *target, EdgeKind::Normal);
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
self.check_bb(location, *unwind, EdgeKind::Unwind); self.check_bb(location, *unwind, EdgeKind::Unwind);
} }
} }
TerminatorKind::DropAndReplace { target, unwind, .. } => { TerminatorKind::DropAndReplace { target, unwind, .. } => {
self.check_bb(location, *target, EdgeKind::Other); self.check_bb(location, *target, EdgeKind::Normal);
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
self.check_bb(location, *unwind, EdgeKind::Unwind); self.check_bb(location, *unwind, EdgeKind::Unwind);
} }
@ -153,7 +153,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
), ),
} }
if let Some((_, target)) = destination { if let Some((_, target)) = destination {
self.check_bb(location, *target, EdgeKind::Other); self.check_bb(location, *target, EdgeKind::Normal);
} }
if let Some(cleanup) = cleanup { if let Some(cleanup) = cleanup {
self.check_bb(location, *cleanup, EdgeKind::Unwind); self.check_bb(location, *cleanup, EdgeKind::Unwind);
@ -170,30 +170,30 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
), ),
); );
} }
self.check_bb(location, *target, EdgeKind::Other); self.check_bb(location, *target, EdgeKind::Normal);
if let Some(cleanup) = cleanup { if let Some(cleanup) = cleanup {
self.check_bb(location, *cleanup, EdgeKind::Unwind); self.check_bb(location, *cleanup, EdgeKind::Unwind);
} }
} }
TerminatorKind::Yield { resume, drop, .. } => { TerminatorKind::Yield { resume, drop, .. } => {
self.check_bb(location, *resume, EdgeKind::Other); self.check_bb(location, *resume, EdgeKind::Normal);
if let Some(drop) = drop { if let Some(drop) = drop {
self.check_bb(location, *drop, EdgeKind::Other); self.check_bb(location, *drop, EdgeKind::Normal);
} }
} }
TerminatorKind::FalseEdge { real_target, imaginary_target } => { TerminatorKind::FalseEdge { real_target, imaginary_target } => {
self.check_bb(location, *real_target, EdgeKind::Other); self.check_bb(location, *real_target, EdgeKind::Normal);
self.check_bb(location, *imaginary_target, EdgeKind::Other); self.check_bb(location, *imaginary_target, EdgeKind::Normal);
} }
TerminatorKind::FalseUnwind { real_target, unwind } => { TerminatorKind::FalseUnwind { real_target, unwind } => {
self.check_bb(location, *real_target, EdgeKind::Other); self.check_bb(location, *real_target, EdgeKind::Normal);
if let Some(unwind) = unwind { if let Some(unwind) = unwind {
self.check_bb(location, *unwind, EdgeKind::Unwind); self.check_bb(location, *unwind, EdgeKind::Unwind);
} }
} }
TerminatorKind::InlineAsm { destination, .. } => { TerminatorKind::InlineAsm { destination, .. } => {
if let Some(destination) = destination { if let Some(destination) = destination {
self.check_bb(location, *destination, EdgeKind::Other); self.check_bb(location, *destination, EdgeKind::Normal);
} }
} }
// Nothing to validate for these. // Nothing to validate for these.