Skip to content

Commit 5ac41a1

Browse files
Don't insert panic when generator can not unwind
1 parent 425e7e5 commit 5ac41a1

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

src/librustc_mir/transform/generator.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,45 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
10081008
false
10091009
}
10101010

1011+
fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
1012+
// Nothing can unwind when landing pads are off.
1013+
if tcx.sess.no_landing_pads() {
1014+
return false;
1015+
}
1016+
1017+
// Unwinds can only start at certain terminators.
1018+
for block in body.basic_blocks() {
1019+
match block.terminator().kind {
1020+
// These never unwind.
1021+
TerminatorKind::Goto { .. }
1022+
| TerminatorKind::SwitchInt { .. }
1023+
| TerminatorKind::Abort
1024+
| TerminatorKind::Return
1025+
| TerminatorKind::Unreachable
1026+
| TerminatorKind::GeneratorDrop
1027+
| TerminatorKind::FalseEdges { .. }
1028+
| TerminatorKind::FalseUnwind { .. } => {}
1029+
1030+
// Resume will *continue* unwinding, but if there's no other unwinding terminator it
1031+
// will never be reached.
1032+
TerminatorKind::Resume => {}
1033+
1034+
TerminatorKind::Yield { .. } => {
1035+
unreachable!("`can_unwind` called before generator transform")
1036+
}
1037+
1038+
// These may unwind.
1039+
TerminatorKind::Drop { .. }
1040+
| TerminatorKind::DropAndReplace { .. }
1041+
| TerminatorKind::Call { .. }
1042+
| TerminatorKind::Assert { .. } => return true,
1043+
}
1044+
}
1045+
1046+
// If we didn't find an unwinding terminator, the function cannot unwind.
1047+
false
1048+
}
1049+
10111050
fn create_generator_resume_function<'tcx>(
10121051
tcx: TyCtxt<'tcx>,
10131052
transform: TransformVisitor<'tcx>,
@@ -1041,7 +1080,12 @@ fn create_generator_resume_function<'tcx>(
10411080
);
10421081
}
10431082

1044-
cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))));
1083+
if can_unwind(tcx, body) {
1084+
cases.insert(
1085+
2,
1086+
(POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))),
1087+
);
1088+
}
10451089

10461090
insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
10471091

0 commit comments

Comments
 (0)