@@ -593,17 +593,28 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
593593 _ => { }
594594 }
595595
596+ // Now where do we jump next?
597+
598+ // Determine if we leave this function normally or via unwinding.
599+ let cur_unwinding = match stack_pop_info {
600+ StackPopInfo :: StartUnwinding => true ,
601+ StackPopInfo :: StopUnwinding => false ,
602+ _ => unwinding
603+ } ;
604+
596605 // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
597606 // In that case, we return early. We also avoid validation in that case,
598607 // because this is CTFE and the final value will be thoroughly validated anyway.
599- let cleanup = unwinding || match frame. return_to_block {
600- StackPopCleanup :: Goto { .. } => true ,
601- StackPopCleanup :: None { cleanup , .. } => {
602- cleanup
603- }
608+ let ( cleanup, next_block ) = match frame. return_to_block {
609+ StackPopCleanup :: Goto { ret , unwind } => {
610+ ( true , Some ( if cur_unwinding { unwind } else { ret } ) )
611+ } ,
612+ StackPopCleanup :: None { cleanup , .. } => ( cleanup , None )
604613 } ;
614+
605615 if !cleanup {
606616 assert ! ( self . stack. is_empty( ) , "only the topmost frame should ever be leaked" ) ;
617+ assert ! ( next_block. is_none( ) , "tried to skip cleanup when we have a next block!" ) ;
607618 // Leak the locals, skip validation.
608619 return Ok ( ( ) ) ;
609620 }
@@ -613,29 +624,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
613624 self . deallocate_local ( local. value ) ?;
614625 }
615626
616- // Now where do we jump next?
617-
618- // Determine if we leave this function normally or via unwinding.
619- let cur_unwinding = match stack_pop_info {
620- StackPopInfo :: StartUnwinding => true ,
621- StackPopInfo :: StopUnwinding => false ,
622- _ => unwinding
623- } ;
624627
625628 trace ! ( "StackPopCleanup: {:?} StackPopInfo: {:?} cur_unwinding = {:?}" ,
626629 frame. return_to_block, stack_pop_info, cur_unwinding) ;
627630 if cur_unwinding {
628631 // Follow the unwind edge.
629- match frame. return_to_block {
630- StackPopCleanup :: Goto { unwind, .. } => {
631- let next_frame = self . frame_mut ( ) ;
632- // If `unwind` is `None`, we'll leave that function immediately again.
633- next_frame. block = unwind;
634- next_frame. stmt = 0 ;
635- } ,
636- StackPopCleanup :: None { .. } =>
637- bug ! ( "Encountered StackPopCleanup::None while unwinding" ) ,
638- }
632+ let unwind = next_block. expect ( "Encounted StackPopCleanup::None when unwinding!" ) ;
633+ let next_frame = self . frame_mut ( ) ;
634+ // If `unwind` is `None`, we'll leave that function immediately again.
635+ next_frame. block = unwind;
636+ next_frame. stmt = 0 ;
639637 } else {
640638 // Follow the normal return edge.
641639 // Validate the return value. Do this after deallocating so that we catch dangling
@@ -661,11 +659,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
661659 }
662660
663661 // Jump to new block -- *after* validation so that the spans make more sense.
664- match frame. return_to_block {
665- StackPopCleanup :: Goto { ret, .. } => {
666- self . goto_block ( ret) ?;
667- }
668- StackPopCleanup :: None { .. } => { }
662+ if let Some ( ret) = next_block {
663+ self . goto_block ( ret) ?;
669664 }
670665 }
671666
0 commit comments