@@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId;
99use  rustc:: mir:: { 
1010    AggregateKind ,  Constant ,  Location ,  Place ,  PlaceBase ,  Body ,  Operand ,  Rvalue ,  Local ,  UnOp , 
1111    StatementKind ,  Statement ,  LocalKind ,  TerminatorKind ,  Terminator ,   ClearCrossCrate ,  SourceInfo , 
12-     BinOp ,  SourceScope ,  SourceScopeLocalData ,  LocalDecl ,  BasicBlock , 
12+     BinOp ,  SourceScope ,  SourceScopeLocalData ,  LocalDecl ,  BasicBlock ,   RETURN_PLACE , 
1313} ; 
1414use  rustc:: mir:: visit:: { 
1515    Visitor ,  PlaceContext ,  MutatingUseContext ,  MutVisitor ,  NonMutatingUseContext , 
@@ -25,6 +25,7 @@ use rustc::ty::layout::{
2525    LayoutOf ,  TyLayout ,  LayoutError ,  HasTyCtxt ,  TargetDataLayout ,  HasDataLayout , 
2626} ; 
2727
28+ use  crate :: rustc:: ty:: subst:: Subst ; 
2829use  crate :: interpret:: { 
2930    self ,  InterpCx ,  ScalarMaybeUndef ,  Immediate ,  OpTy , 
3031    StackPopCleanup ,  LocalValue ,  LocalState ,  AllocId ,  Frame , 
@@ -269,6 +270,7 @@ struct ConstPropagator<'mir, 'tcx> {
269270    param_env :  ParamEnv < ' tcx > , 
270271    source_scope_local_data :  ClearCrossCrate < IndexVec < SourceScope ,  SourceScopeLocalData > > , 
271272    local_decls :  IndexVec < Local ,  LocalDecl < ' tcx > > , 
273+     ret :  Option < OpTy < ' tcx ,  ( ) > > , 
272274} 
273275
274276impl < ' mir ,  ' tcx >  LayoutOf  for  ConstPropagator < ' mir ,  ' tcx >  { 
@@ -308,11 +310,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
308310        let  mut  ecx = InterpCx :: new ( tcx. at ( span) ,  param_env,  ConstPropMachine ,  ( ) ) ; 
309311        let  can_const_prop = CanConstProp :: check ( body) ; 
310312
313+         let  substs = & InternalSubsts :: identity_for_item ( tcx,  def_id) ; 
314+ 
315+         let  ret =
316+             ecx
317+                 . layout_of ( body. return_ty ( ) . subst ( tcx,  substs) ) 
318+                 . ok ( ) 
319+                 // Don't bother allocating memory for ZST types which have no values. 
320+                 . filter ( |ret_layout| !ret_layout. is_zst ( ) ) 
321+                 . map ( |ret_layout| ecx. allocate ( ret_layout,  MemoryKind :: Stack ) ) ; 
322+ 
311323        ecx. push_stack_frame ( 
312-             Instance :: new ( def_id,  & InternalSubsts :: identity_for_item ( tcx ,  def_id ) ) , 
324+             Instance :: new ( def_id,  substs ) , 
313325            span, 
314326            dummy_body, 
315-             None , 
327+             ret . map ( Into :: into ) , 
316328            StackPopCleanup :: None  { 
317329                cleanup :  false , 
318330            } , 
@@ -327,6 +339,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
327339            source_scope_local_data, 
328340            //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it 
329341            local_decls :  body. local_decls . clone ( ) , 
342+             ret :  ret. map ( Into :: into) , 
330343        } 
331344    } 
332345
@@ -335,6 +348,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
335348    } 
336349
337350    fn  get_const ( & self ,  local :  Local )  -> Option < Const < ' tcx > >  { 
351+         if  local == RETURN_PLACE  { 
352+             // Try to read the return place as an immediate so that if it is representable as a 
353+             // scalar, we can handle it as such, but otherwise, just return the value as is. 
354+             return  match  self . ret . map ( |ret| self . ecx . try_read_immediate ( ret) )  { 
355+                 Some ( Ok ( Ok ( imm) ) )  => Some ( imm. into ( ) ) , 
356+                 _ => self . ret , 
357+             } ; 
358+         } 
359+ 
338360        self . ecx . access_local ( self . ecx . frame ( ) ,  local,  None ) . ok ( ) 
339361    } 
340362
@@ -643,7 +665,8 @@ impl CanConstProp {
643665            //        lint for x != y 
644666            // FIXME(oli-obk): lint variables until they are used in a condition 
645667            // FIXME(oli-obk): lint if return value is constant 
646-             * val = body. local_kind ( local)  == LocalKind :: Temp ; 
668+             let  local_kind = body. local_kind ( local) ; 
669+             * val = local_kind == LocalKind :: Temp  || local_kind == LocalKind :: ReturnPointer ; 
647670
648671            if  !* val { 
649672                trace ! ( "local {:?} can't be propagated because it's not a temporary" ,  local) ; 
@@ -731,7 +754,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
731754                            } 
732755                        }  else  { 
733756                            trace ! ( "can't propagate into {:?}" ,  local) ; 
734-                             self . remove_const ( local) ; 
757+                             if  local != RETURN_PLACE  { 
758+                                 self . remove_const ( local) ; 
759+                             } 
735760                        } 
736761                    } 
737762                } 
0 commit comments