@@ -628,35 +628,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
628628        let  frame = M :: init_frame_extra ( self ,  pre_frame) ?; 
629629        self . stack_mut ( ) . push ( frame) ; 
630630
631-         // don't allocate at all for trivial constants 
632-         if  body. local_decls . len ( )  > 1  { 
633-             // Locals are initially uninitialized. 
634-             let  dummy = LocalState  {  value :  LocalValue :: Uninitialized ,  layout :  Cell :: new ( None )  } ; 
635-             let  mut  locals = IndexVec :: from_elem ( dummy,  & body. local_decls ) ; 
636-             // Return place is handled specially by the `eval_place` functions, and the 
637-             // entry in `locals` should never be used. Make it dead, to be sure. 
638-             locals[ mir:: RETURN_PLACE ] . value  = LocalValue :: Dead ; 
639-             // Now mark those locals as dead that we do not want to initialize 
640-             match  self . tcx . def_kind ( instance. def_id ( ) )  { 
641-                 // statics and constants don't have `Storage*` statements, no need to look for them 
642-                 // 
643-                 // FIXME: The above is likely untrue. See 
644-                 // <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it 
645-                 // okay to ignore `StorageDead`/`StorageLive` annotations during CTFE? 
646-                 Some ( DefKind :: Static  | DefKind :: Const  | DefKind :: AssocConst )  => { } 
647-                 _ => { 
648-                     // Mark locals that use `Storage*` annotations as dead on function entry. 
649-                     let  always_live = AlwaysLiveLocals :: new ( self . body ( ) ) ; 
650-                     for  local in  locals. indices ( )  { 
651-                         if  !always_live. contains ( local)  { 
652-                             locals[ local] . value  = LocalValue :: Dead ; 
653-                         } 
631+         // Locals are initially uninitialized. 
632+         let  dummy = LocalState  {  value :  LocalValue :: Uninitialized ,  layout :  Cell :: new ( None )  } ; 
633+         let  mut  locals = IndexVec :: from_elem ( dummy,  & body. local_decls ) ; 
634+ 
635+         // Now mark those locals as dead that we do not want to initialize 
636+         match  self . tcx . def_kind ( instance. def_id ( ) )  { 
637+             // statics and constants don't have `Storage*` statements, no need to look for them 
638+             // 
639+             // FIXME: The above is likely untrue. See 
640+             // <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it 
641+             // okay to ignore `StorageDead`/`StorageLive` annotations during CTFE? 
642+             Some ( DefKind :: Static  | DefKind :: Const  | DefKind :: AssocConst )  => { } 
643+             _ => { 
644+                 // Mark locals that use `Storage*` annotations as dead on function entry. 
645+                 let  always_live = AlwaysLiveLocals :: new ( self . body ( ) ) ; 
646+                 for  local in  locals. indices ( )  { 
647+                     if  !always_live. contains ( local)  { 
648+                         locals[ local] . value  = LocalValue :: Dead ; 
654649                    } 
655650                } 
656651            } 
657-             // done 
658-             self . frame_mut ( ) . locals  = locals; 
659652        } 
653+         // done 
654+         self . frame_mut ( ) . locals  = locals; 
660655
661656        M :: after_stack_push ( self ) ?; 
662657        info ! ( "ENTERING({}) {}" ,  self . frame_idx( ) ,  self . frame( ) . instance) ; 
@@ -734,6 +729,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
734729        let  frame =
735730            self . stack_mut ( ) . pop ( ) . expect ( "tried to pop a stack frame, but there were none" ) ; 
736731
732+         if  !unwinding { 
733+             // Copy the return value to the caller's stack frame. 
734+             if  let  Some ( return_place)  = frame. return_place  { 
735+                 let  op = self . access_local ( & frame,  mir:: RETURN_PLACE ,  None ) ?; 
736+                 self . copy_op_transmute ( op,  return_place) ?; 
737+                 self . dump_place ( * return_place) ; 
738+             }  else  { 
739+                 throw_ub ! ( Unreachable ) ; 
740+             } 
741+         } 
742+ 
737743        // Now where do we jump next? 
738744
739745        // Usually we want to clean up (deallocate locals), but in a few rare cases we don't. 
@@ -759,7 +765,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
759765            self . deallocate_local ( local. value ) ?; 
760766        } 
761767
762-         let  return_place = frame. return_place ; 
763768        if  M :: after_stack_pop ( self ,  frame,  unwinding) ? == StackPopJump :: NoJump  { 
764769            // The hook already did everything. 
765770            // We want to skip the `info!` below, hence early return. 
@@ -772,25 +777,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
772777            self . unwind_to_block ( unwind) ; 
773778        }  else  { 
774779            // Follow the normal return edge. 
775-             // Validate the return value. Do this after deallocating so that we catch dangling 
776-             // references. 
777-             if  let  Some ( return_place)  = return_place { 
778-                 if  M :: enforce_validity ( self )  { 
779-                     // Data got changed, better make sure it matches the type! 
780-                     // It is still possible that the return place held invalid data while 
781-                     // the function is running, but that's okay because nobody could have 
782-                     // accessed that same data from the "outside" to observe any broken 
783-                     // invariant -- that is, unless a function somehow has a ptr to 
784-                     // its return place... but the way MIR is currently generated, the 
785-                     // return place is always a local and then this cannot happen. 
786-                     self . validate_operand ( self . place_to_op ( return_place) ?) ?; 
787-                 } 
788-             }  else  { 
789-                 // Uh, that shouldn't happen... the function did not intend to return 
790-                 throw_ub ! ( Unreachable ) ; 
791-             } 
792- 
793-             // Jump to new block -- *after* validation so that the spans make more sense. 
794780            if  let  Some ( ret)  = next_block { 
795781                self . return_to_block ( ret) ?; 
796782            } 
0 commit comments