@@ -575,8 +575,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
575
575
}
576
576
577
577
// 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 ) ;
580
588
581
589
return None ;
582
590
}
@@ -716,6 +724,9 @@ enum ConstPropMode {
716
724
OnlyInsideOwnBlock ,
717
725
/// The `Local` can be propagated into but reads cannot be propagated.
718
726
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 ,
719
730
}
720
731
721
732
struct CanConstProp {
@@ -781,7 +792,9 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
781
792
// end of the block anyway, and inside the block we overwrite previous
782
793
// states as applicable.
783
794
ConstPropMode :: OnlyInsideOwnBlock => { }
784
- other => {
795
+ ConstPropMode :: NoPropagation => { }
796
+ ConstPropMode :: OnlyPropagateInto => { }
797
+ other @ ConstPropMode :: FullConstProp => {
785
798
trace ! (
786
799
"local {:?} can't be propagated because of multiple assignments" ,
787
800
local,
@@ -813,7 +826,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
813
826
| MutatingUse ( MutatingUseContext :: Borrow )
814
827
| MutatingUse ( MutatingUseContext :: AddressOf ) => {
815
828
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 ;
817
830
}
818
831
}
819
832
}
@@ -858,19 +871,22 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
858
871
}
859
872
}
860
873
}
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 ) ;
873
882
}
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 => { }
874
890
}
875
891
} else {
876
892
// Const prop failed, so erase the destination, ensuring that whatever happens
@@ -890,6 +906,12 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
890
906
) ;
891
907
Self :: remove_const ( & mut self . ecx , place. local ) ;
892
908
}
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 ) ;
893
915
}
894
916
} else {
895
917
match statement. kind {
0 commit comments