@@ -575,8 +575,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
575575 }
576576
577577 // Do not try creating references (#67862)
578- Rvalue :: Ref ( _, _, place_ref) => {
579- trace ! ( "skipping Ref({:?})" , place_ref) ;
578+ Rvalue :: AddressOf ( _, place) | Rvalue :: Ref ( _, _, place) => {
579+ trace ! ( "skipping AddressOf | Ref for {:?}" , place) ;
580+
581+ // This may be creating mutable references or immutable references to cells.
582+ // If that happens, the pointed to value could be mutated via that reference.
583+ // Since we aren't tracking references, the const propagator loses track of what
584+ // value the local has right now.
585+ // Thus, all locals that have their reference taken
586+ // must not take part in propagation.
587+ Self :: remove_const ( & mut self . ecx , place. local ) ;
580588
581589 return None ;
582590 }
@@ -716,6 +724,9 @@ enum ConstPropMode {
716724 OnlyInsideOwnBlock ,
717725 /// The `Local` can be propagated into but reads cannot be propagated.
718726 OnlyPropagateInto ,
727+ /// The `Local` cannot be part of propagation at all. Any statement
728+ /// referencing it either for reading or writing will not get propagated.
729+ NoPropagation ,
719730}
720731
721732struct CanConstProp {
@@ -781,7 +792,9 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
781792 // end of the block anyway, and inside the block we overwrite previous
782793 // states as applicable.
783794 ConstPropMode :: OnlyInsideOwnBlock => { }
784- other => {
795+ ConstPropMode :: NoPropagation => { }
796+ ConstPropMode :: OnlyPropagateInto => { }
797+ other @ ConstPropMode :: FullConstProp => {
785798 trace ! (
786799 "local {:?} can't be propagated because of multiple assignments" ,
787800 local,
@@ -813,7 +826,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
813826 | MutatingUse ( MutatingUseContext :: Borrow )
814827 | MutatingUse ( MutatingUseContext :: AddressOf ) => {
815828 trace ! ( "local {:?} can't be propagaged because it's used: {:?}" , local, context) ;
816- self . can_const_prop [ local] = ConstPropMode :: OnlyPropagateInto ;
829+ self . can_const_prop [ local] = ConstPropMode :: NoPropagation ;
817830 }
818831 }
819832 }
@@ -858,19 +871,22 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
858871 }
859872 }
860873 }
861- if can_const_prop == ConstPropMode :: OnlyInsideOwnBlock {
862- trace ! (
863- "found local restricted to its block. Will remove it from const-prop after block is finished. Local: {:?}" ,
864- place. local
865- ) ;
866- self . locals_of_current_block . insert ( place. local ) ;
867- }
868-
869- if can_const_prop == ConstPropMode :: OnlyPropagateInto {
870- trace ! ( "can't propagate into {:?}" , place) ;
871- if place. local != RETURN_PLACE {
872- Self :: remove_const ( & mut self . ecx , place. local ) ;
874+ match can_const_prop {
875+ ConstPropMode :: OnlyInsideOwnBlock => {
876+ trace ! (
877+ "found local restricted to its block. \
878+ Will remove it from const-prop after block is finished. Local: {:?}",
879+ place. local
880+ ) ;
881+ self . locals_of_current_block . insert ( place. local ) ;
873882 }
883+ ConstPropMode :: OnlyPropagateInto | ConstPropMode :: NoPropagation => {
884+ trace ! ( "can't propagate into {:?}" , place) ;
885+ if place. local != RETURN_PLACE {
886+ Self :: remove_const ( & mut self . ecx , place. local ) ;
887+ }
888+ }
889+ ConstPropMode :: FullConstProp => { }
874890 }
875891 } else {
876892 // Const prop failed, so erase the destination, ensuring that whatever happens
@@ -890,6 +906,12 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
890906 ) ;
891907 Self :: remove_const ( & mut self . ecx , place. local ) ;
892908 }
909+ } else {
910+ trace ! (
911+ "cannot propagate into {:?}, because the type of the local is generic." ,
912+ place,
913+ ) ;
914+ Self :: remove_const ( & mut self . ecx , place. local ) ;
893915 }
894916 } else {
895917 match statement. kind {
0 commit comments