@@ -593,17 +593,28 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
593
593
_ => { }
594
594
}
595
595
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
+
596
605
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
597
606
// In that case, we return early. We also avoid validation in that case,
598
607
// 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 )
604
613
} ;
614
+
605
615
if !cleanup {
606
616
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!" ) ;
607
618
// Leak the locals, skip validation.
608
619
return Ok ( ( ) ) ;
609
620
}
@@ -613,29 +624,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
613
624
self . deallocate_local ( local. value ) ?;
614
625
}
615
626
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
- } ;
624
627
625
628
trace ! ( "StackPopCleanup: {:?} StackPopInfo: {:?} cur_unwinding = {:?}" ,
626
629
frame. return_to_block, stack_pop_info, cur_unwinding) ;
627
630
if cur_unwinding {
628
631
// 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 ;
639
637
} else {
640
638
// Follow the normal return edge.
641
639
// 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> {
661
659
}
662
660
663
661
// 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) ?;
669
664
}
670
665
}
671
666
0 commit comments