@@ -262,7 +262,7 @@ struct ConstPropagator<'mir, 'tcx> {
262262    ecx :  InterpCx < ' mir ,  ' tcx ,  ConstPropMachine > , 
263263    tcx :  TyCtxt < ' tcx > , 
264264    source :  MirSource < ' tcx > , 
265-     can_const_prop :  IndexVec < Local ,  bool > , 
265+     can_const_prop :  IndexVec < Local ,  ConstPropMode > , 
266266    param_env :  ParamEnv < ' tcx > , 
267267    // FIXME(eddyb) avoid cloning these two fields more than once, 
268268    // by accessing them through `ecx` instead. 
@@ -708,17 +708,28 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
708708    } 
709709} 
710710
711+ /// The mode that `ConstProp` is allowed to run in for a given `Local`. 
712+ #[ derive( Clone ,  Copy ,  Debug ,  PartialEq ) ]  
713+ enum  ConstPropMode  { 
714+     /// The `Local` can be propagated into and reads of this `Local` can also be propagated. 
715+      FullConstProp , 
716+     /// The `Local` can be propagated into but reads cannot be propagated. 
717+      OnlyPropagateInto , 
718+     /// No propagation is allowed at all. 
719+      NoPropagation , 
720+ } 
721+ 
711722struct  CanConstProp  { 
712-     can_const_prop :  IndexVec < Local ,  bool > , 
723+     can_const_prop :  IndexVec < Local ,  ConstPropMode > , 
713724    // false at the beginning, once set, there are not allowed to be any more assignments 
714725    found_assignment :  IndexVec < Local ,  bool > , 
715726} 
716727
717728impl  CanConstProp  { 
718729    /// returns true if `local` can be propagated 
719-      fn  check ( body :  ReadOnlyBodyAndCache < ' _ ,  ' _ > )  -> IndexVec < Local ,  bool >  { 
730+      fn  check ( body :  ReadOnlyBodyAndCache < ' _ ,  ' _ > )  -> IndexVec < Local ,  ConstPropMode >  { 
720731        let  mut  cpv = CanConstProp  { 
721-             can_const_prop :  IndexVec :: from_elem ( true ,  & body. local_decls ) , 
732+             can_const_prop :  IndexVec :: from_elem ( ConstPropMode :: FullConstProp ,  & body. local_decls ) , 
722733            found_assignment :  IndexVec :: from_elem ( false ,  & body. local_decls ) , 
723734        } ; 
724735        for  ( local,  val)  in  cpv. can_const_prop . iter_enumerated_mut ( )  { 
@@ -728,10 +739,10 @@ impl CanConstProp {
728739            // FIXME(oli-obk): lint variables until they are used in a condition 
729740            // FIXME(oli-obk): lint if return value is constant 
730741            let  local_kind = body. local_kind ( local) ; 
731-             * val = local_kind == LocalKind :: Temp  || local_kind == LocalKind :: ReturnPointer ; 
732742
733-             if  !* val { 
734-                 trace ! ( "local {:?} can't be propagated because it's not a temporary" ,  local) ; 
743+             if  local_kind == LocalKind :: Arg  || local_kind == LocalKind :: Var  { 
744+                 * val = ConstPropMode :: OnlyPropagateInto ; 
745+                 trace ! ( "local {:?} can't be const propagated because it's not a temporary" ,  local) ; 
735746            } 
736747        } 
737748        cpv. visit_body ( body) ; 
@@ -753,7 +764,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
753764            // only occur in independent execution paths 
754765            MutatingUse ( MutatingUseContext :: Store )  => if  self . found_assignment [ local]  { 
755766                trace ! ( "local {:?} can't be propagated because of multiple assignments" ,  local) ; 
756-                 self . can_const_prop [ local]  = false ; 
767+                 self . can_const_prop [ local]  = ConstPropMode :: NoPropagation ; 
757768            }  else  { 
758769                self . found_assignment [ local]  = true 
759770            } , 
@@ -766,7 +777,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
766777            NonUse ( _)  => { } , 
767778            _ => { 
768779                trace ! ( "local {:?} can't be propagaged because it's used: {:?}" ,  local,  context) ; 
769-                 self . can_const_prop [ local]  = false ; 
780+                 self . can_const_prop [ local]  = ConstPropMode :: NoPropagation ; 
770781            } , 
771782        } 
772783    } 
@@ -800,10 +811,10 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
800811            if  let  Ok ( place_layout)  = self . tcx . layout_of ( self . param_env . and ( place_ty) )  { 
801812                if  let  Some ( local)  = place. as_local ( )  { 
802813                    let  source = statement. source_info ; 
814+                     let  can_const_prop = self . can_const_prop [ local] ; 
803815                    if  let  Some ( ( ) )  = self . const_prop ( rval,  place_layout,  source,  place)  { 
804-                         if  self . can_const_prop [ local]  { 
805-                             trace ! ( "propagated into {:?}" ,  local) ; 
806- 
816+                         if  can_const_prop == ConstPropMode :: FullConstProp  ||
817+                            can_const_prop == ConstPropMode :: OnlyPropagateInto  { 
807818                            if  let  Some ( value)  = self . get_const ( local)  { 
808819                                if  self . should_const_prop ( value)  { 
809820                                    trace ! ( "replacing {:?} with {:?}" ,  rval,  value) ; 
@@ -812,21 +823,26 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
812823                                        value, 
813824                                        statement. source_info , 
814825                                    ) ; 
826+ 
827+                                     if  can_const_prop == ConstPropMode :: FullConstProp  { 
828+                                         trace ! ( "propagated into {:?}" ,  local) ; 
829+                                     } 
815830                                } 
816831                            } 
817-                         }  else  { 
818-                             trace ! ( "can't propagate into {:?}" ,  local) ; 
819-                             if  local != RETURN_PLACE  { 
820-                                 self . remove_const ( local) ; 
821-                             } 
832+                         } 
833+                     } 
834+                     if  self . can_const_prop [ local]  != ConstPropMode :: FullConstProp  { 
835+                         trace ! ( "can't propagate into {:?}" ,  local) ; 
836+                         if  local != RETURN_PLACE  { 
837+                             self . remove_const ( local) ; 
822838                        } 
823839                    } 
824840                } 
825841            } 
826842        }  else  { 
827843            match  statement. kind  { 
828844                StatementKind :: StorageLive ( local)  |
829-                 StatementKind :: StorageDead ( local)  if   self . can_const_prop [ local ]   => { 
845+                 StatementKind :: StorageDead ( local)  => { 
830846                    let  frame = self . ecx . frame_mut ( ) ; 
831847                    frame. locals [ local] . value  =
832848                        if  let  StatementKind :: StorageLive ( _)  = statement. kind  { 
0 commit comments