Skip to content

Commit 5e68c57

Browse files
committed
Use the correct state for poisoning a generator
1 parent 8a78019 commit 5e68c57

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed

src/librustc_mir/transform/generator.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
//! }
2727
//!
2828
//! This pass computes the meaning of the state field and the MIR locals which are live
29-
//! across a suspension point. There are however two hardcoded generator states:
29+
//! across a suspension point. There are however three hardcoded generator states:
3030
//! 0 - Generator have not been resumed yet
3131
//! 1 - Generator has returned / is completed
3232
//! 2 - Generator has been poisoned
@@ -144,6 +144,13 @@ fn self_arg() -> Local {
144144
Local::new(1)
145145
}
146146

147+
/// Generator have not been resumed yet
148+
const UNRESUMED: u32 = 0;
149+
/// Generator has returned / is completed
150+
const RETURNED: u32 = 1;
151+
/// Generator has been poisoned
152+
const POISONED: u32 = 2;
153+
147154
struct SuspensionPoint {
148155
state: u32,
149156
resume: BasicBlock,
@@ -278,7 +285,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
278285

279286
state
280287
} else { // Return
281-
1 // state for returned
288+
RETURNED // state for returned
282289
};
283290
data.statements.push(self.set_state(state, source_info));
284291
data.terminator.as_mut().unwrap().kind = TerminatorKind::Return;
@@ -643,10 +650,10 @@ fn create_generator_drop_shim<'a, 'tcx>(
643650

644651
let mut cases = create_cases(&mut mir, transform, |point| point.drop);
645652

646-
cases.insert(0, (0, drop_clean));
653+
cases.insert(0, (UNRESUMED, drop_clean));
647654

648-
// The returned state (1) and the poisoned state (2) falls through to
649-
// the default case which is just to return
655+
// The returned state and the poisoned state fall through to the default
656+
// case which is just to return
650657

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

@@ -762,7 +769,7 @@ fn create_generator_resume_function<'a, 'tcx>(
762769
for block in mir.basic_blocks_mut() {
763770
let source_info = block.terminator().source_info;
764771
if let &TerminatorKind::Resume = &block.terminator().kind {
765-
block.statements.push(transform.set_state(1, source_info));
772+
block.statements.push(transform.set_state(POISONED, source_info));
766773
}
767774
}
768775

@@ -773,12 +780,12 @@ fn create_generator_resume_function<'a, 'tcx>(
773780
GeneratorResumedAfterReturn,
774781
};
775782

776-
// Jump to the entry point on the 0 state
777-
cases.insert(0, (0, BasicBlock::new(0)));
778-
// Panic when resumed on the returned (1) state
779-
cases.insert(1, (1, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn)));
780-
// Panic when resumed on the poisoned (2) state
781-
cases.insert(2, (2, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic)));
783+
// Jump to the entry point on the unresumed
784+
cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
785+
// Panic when resumed on the returned state
786+
cases.insert(1, (RETURNED, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn)));
787+
// Panic when resumed on the poisoned state
788+
cases.insert(2, (POISONED, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic)));
782789

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

@@ -942,7 +949,7 @@ impl MirPass for StateTransform {
942949
mir.generator_layout = Some(layout);
943950

944951
// Insert `drop(generator_struct)` which is used to drop upvars for generators in
945-
// the unresumed (0) state.
952+
// the unresumed state.
946953
// This is expanded to a drop ladder in `elaborate_generator_drops`.
947954
let drop_clean = insert_clean_drop(mir);
948955

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// error-pattern:generator resumed after panicking
2+
3+
// Test that we get the correct message for resuming a panicked generator.
4+
5+
#![feature(generators, generator_trait)]
6+
7+
use std::{
8+
ops::Generator,
9+
pin::Pin,
10+
panic,
11+
};
12+
13+
fn main() {
14+
let mut g = || {
15+
panic!();
16+
yield;
17+
};
18+
panic::catch_unwind(panic::AssertUnwindSafe(|| {
19+
let x = Pin::new(&mut g).resume();
20+
}));
21+
Pin::new(&mut g).resume();
22+
}

0 commit comments

Comments
 (0)