Skip to content

Commit 425e7e5

Browse files
Don't insert panic when generator can not return
1 parent 823ff8c commit 425e7e5

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

src/librustc_mir/transform/generator.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -991,12 +991,30 @@ fn insert_panic_block<'tcx>(
991991
assert_block
992992
}
993993

994+
fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
995+
// Returning from a function with an uninhabited return type is undefined behavior.
996+
if body.return_ty().conservative_is_privately_uninhabited(tcx) {
997+
return false;
998+
}
999+
1000+
// If there's no return terminator the function also won't return.
1001+
for block in body.basic_blocks() {
1002+
if let TerminatorKind::Return = block.terminator().kind {
1003+
return true;
1004+
}
1005+
}
1006+
1007+
// Otherwise we assume that the function may return.
1008+
false
1009+
}
1010+
9941011
fn create_generator_resume_function<'tcx>(
9951012
tcx: TyCtxt<'tcx>,
9961013
transform: TransformVisitor<'tcx>,
9971014
def_id: DefId,
9981015
source: MirSource<'tcx>,
9991016
body: &mut BodyAndCache<'tcx>,
1017+
can_return: bool,
10001018
) {
10011019
// Poison the generator when it unwinds
10021020
for block in body.basic_blocks_mut() {
@@ -1015,7 +1033,14 @@ fn create_generator_resume_function<'tcx>(
10151033

10161034
// Panic when resumed on the returned or poisoned state
10171035
let generator_kind = body.generator_kind.unwrap();
1018-
cases.insert(1, (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))));
1036+
1037+
if can_return {
1038+
cases.insert(
1039+
1,
1040+
(RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))),
1041+
);
1042+
}
1043+
10191044
cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))));
10201045

10211046
insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
@@ -1200,6 +1225,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
12001225
let (remap, layout, storage_liveness) =
12011226
compute_layout(tcx, source, &upvars, interior, movable, body);
12021227

1228+
let can_return = can_return(tcx, body);
1229+
12031230
// Run the transformation which converts Places from Local to generator struct
12041231
// accesses for locals in `remap`.
12051232
// It also rewrites `return x` and `yield y` as writing a new generator state and returning
@@ -1243,6 +1270,6 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
12431270
body.generator_drop = Some(box drop_shim);
12441271

12451272
// Create the Generator::resume function
1246-
create_generator_resume_function(tcx, transform, def_id, source, body);
1273+
create_generator_resume_function(tcx, transform, def_id, source, body, can_return);
12471274
}
12481275
}

0 commit comments

Comments
 (0)