@@ -991,12 +991,30 @@ fn insert_panic_block<'tcx>(
991
991
assert_block
992
992
}
993
993
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
+
994
1011
fn create_generator_resume_function < ' tcx > (
995
1012
tcx : TyCtxt < ' tcx > ,
996
1013
transform : TransformVisitor < ' tcx > ,
997
1014
def_id : DefId ,
998
1015
source : MirSource < ' tcx > ,
999
1016
body : & mut BodyAndCache < ' tcx > ,
1017
+ can_return : bool ,
1000
1018
) {
1001
1019
// Poison the generator when it unwinds
1002
1020
for block in body. basic_blocks_mut ( ) {
@@ -1015,7 +1033,14 @@ fn create_generator_resume_function<'tcx>(
1015
1033
1016
1034
// Panic when resumed on the returned or poisoned state
1017
1035
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
+
1019
1044
cases. insert ( 2 , ( POISONED , insert_panic_block ( tcx, body, ResumedAfterPanic ( generator_kind) ) ) ) ;
1020
1045
1021
1046
insert_switch ( body, cases, & transform, TerminatorKind :: Unreachable ) ;
@@ -1200,6 +1225,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
1200
1225
let ( remap, layout, storage_liveness) =
1201
1226
compute_layout ( tcx, source, & upvars, interior, movable, body) ;
1202
1227
1228
+ let can_return = can_return ( tcx, body) ;
1229
+
1203
1230
// Run the transformation which converts Places from Local to generator struct
1204
1231
// accesses for locals in `remap`.
1205
1232
// 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 {
1243
1270
body. generator_drop = Some ( box drop_shim) ;
1244
1271
1245
1272
// 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 ) ;
1247
1274
}
1248
1275
}
0 commit comments