@@ -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+
9941011fn 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