Skip to content

Make the fallback of generator resumption be unreachable instead of using return #44747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 23, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions src/librustc_mir/transform/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,15 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &mut Mir<'tcx>,
cases: Vec<(u32, BasicBlock)>,
transform: &TransformVisitor<'a, 'tcx>) {
let return_block = insert_return_block(mir);
transform: &TransformVisitor<'a, 'tcx>,
default: TerminatorKind<'tcx>) {
let default_block = insert_term_block(mir, default);

let switch = TerminatorKind::SwitchInt {
discr: Operand::Consume(transform.make_field(transform.state_field, tcx.types.u32)),
switch_ty: tcx.types.u32,
values: Cow::from(cases.iter().map(|&(i, _)| ConstInt::U32(i)).collect::<Vec<_>>()),
targets: cases.iter().map(|&(_, d)| d).chain(once(return_block)).collect(),
targets: cases.iter().map(|&(_, d)| d).chain(once(default_block)).collect(),
};

let source_info = source_info(mir);
Expand Down Expand Up @@ -542,7 +543,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
// The returned state (1) and the poisoned state (2) falls through to
// the default case which is just to return

insert_switch(tcx, &mut mir, cases, &transform);
insert_switch(tcx, &mut mir, cases, &transform, TerminatorKind::Return);

for block in mir.basic_blocks_mut() {
let kind = &mut block.terminator_mut().kind;
Expand Down Expand Up @@ -588,18 +589,18 @@ fn create_generator_drop_shim<'a, 'tcx>(
mir
}

fn insert_return_block<'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
let return_block = BasicBlock::new(mir.basic_blocks().len());
fn insert_term_block<'tcx>(mir: &mut Mir<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
let term_block = BasicBlock::new(mir.basic_blocks().len());
let source_info = source_info(mir);
mir.basic_blocks_mut().push(BasicBlockData {
statements: Vec::new(),
terminator: Some(Terminator {
source_info,
kind: TerminatorKind::Return,
kind,
}),
is_cleanup: false,
});
return_block
term_block
}

fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Expand Down Expand Up @@ -659,7 +660,7 @@ fn create_generator_resume_function<'a, 'tcx>(
// Panic when resumed on the poisoned (2) state
cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic)));

insert_switch(tcx, mir, cases, &transform);
insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable);

make_generator_state_argument_indirect(tcx, def_id, mir);

Expand All @@ -680,7 +681,7 @@ fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo {
}

fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
let return_block = insert_return_block(mir);
let return_block = insert_term_block(mir, TerminatorKind::Return);

// Create a block to destroy an unresumed generators. This can only destroy upvars.
let drop_clean = BasicBlock::new(mir.basic_blocks().len());
Expand Down