Skip to content

Commit

Permalink
Poison generators when any terminator unwinds
Browse files Browse the repository at this point in the history
This didn't cause issues before since generator types were always
considered to "need drop", leading to unwind paths
(including a `Resume` block) always getting generated.
  • Loading branch information
jonas-schievink committed Mar 7, 2020
1 parent 5ac41a1 commit 46aeef6
Showing 1 changed file with 31 additions and 5 deletions.
36 changes: 31 additions & 5 deletions src/librustc_mir/transform/generator.rs
Expand Up @@ -1055,11 +1055,37 @@ fn create_generator_resume_function<'tcx>(
body: &mut BodyAndCache<'tcx>,
can_return: bool,
) {
let can_unwind = can_unwind(tcx, body);

// Poison the generator when it unwinds
for block in body.basic_blocks_mut() {
let source_info = block.terminator().source_info;
if let &TerminatorKind::Resume = &block.terminator().kind {
block.statements.push(transform.set_discr(VariantIdx::new(POISONED), source_info));
if can_unwind {
let poison_block = BasicBlock::new(body.basic_blocks().len());
let source_info = source_info(body);
body.basic_blocks_mut().push(BasicBlockData {
statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
is_cleanup: true,
});

for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
let source_info = block.terminator().source_info;

if let TerminatorKind::Resume = block.terminator().kind {
// An existing `Resume` terminator is redirected to jump to our dedicated
// "poisoning block" above.
if idx != poison_block {
*block.terminator_mut() = Terminator {
source_info,
kind: TerminatorKind::Goto { target: poison_block },
};
}
} else if !block.is_cleanup {
// Any terminators that *can* unwind but don't have an unwind target set are also
// pointed at our poisoning block (unless they're part of the cleanup path).
if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
*unwind = Some(poison_block);
}
}
}
}

Expand All @@ -1080,7 +1106,7 @@ fn create_generator_resume_function<'tcx>(
);
}

if can_unwind(tcx, body) {
if can_unwind {
cases.insert(
2,
(POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))),
Expand Down

0 comments on commit 46aeef6

Please sign in to comment.