@@ -26,7 +26,7 @@ rustc_index::newtype_index!(
2626 /// This index uniquely identifies a tracked place and therefore a slot in [`State`].
2727 ///
2828 /// It is an implementation detail of this module.
29- struct ValueIndex { }
29+ pub struct ValueIndex { }
3030) ;
3131
3232/// See [`State`].
@@ -211,22 +211,9 @@ impl<V: Clone + HasBottom> State<V> {
211211 /// The target place must have been flooded before calling this method.
212212 pub fn insert_place_idx ( & mut self , target : PlaceIndex , source : PlaceIndex , map : & Map < ' _ > ) {
213213 let State :: Reachable ( values) = self else { return } ;
214-
215- // If both places are tracked, we copy the value to the target.
216- // If the target is tracked, but the source is not, we do nothing, as invalidation has
217- // already been performed.
218- if let Some ( target_value) = map. places [ target] . value_index {
219- if let Some ( source_value) = map. places [ source] . value_index {
220- values. insert ( target_value, values. get ( source_value) . clone ( ) ) ;
221- }
222- }
223- for target_child in map. children ( target) {
224- // Try to find corresponding child and recurse. Reasoning is similar as above.
225- let projection = map. places [ target_child] . proj_elem . unwrap ( ) ;
226- if let Some ( source_child) = map. projections . get ( & ( source, projection) ) {
227- self . insert_place_idx ( target_child, * source_child, map) ;
228- }
229- }
214+ map. for_each_value_pair ( target, source, & mut |target, source| {
215+ values. insert ( target, values. get ( source) . clone ( ) ) ;
216+ } ) ;
230217 }
231218
232219 /// Helper method to interpret `target = result`.
@@ -677,6 +664,26 @@ impl<'tcx> Map<'tcx> {
677664 self . find_extra ( place, [ TrackElem :: DerefLen ] )
678665 }
679666
667+ /// Locates the value corresponding to the given place.
668+ pub fn value ( & self , place : PlaceIndex ) -> Option < ValueIndex > {
669+ self . places [ place] . value_index
670+ }
671+
672+ /// Locates the value corresponding to the given place.
673+ pub fn find_value ( & self , place : PlaceRef < ' _ > ) -> Option < ValueIndex > {
674+ self . value ( self . find ( place) ?)
675+ }
676+
677+ /// Locates the value corresponding to the given discriminant.
678+ pub fn find_discr_value ( & self , place : PlaceRef < ' _ > ) -> Option < ValueIndex > {
679+ self . value ( self . find_discr ( place) ?)
680+ }
681+
682+ /// Locates the value corresponding to the given length.
683+ pub fn find_len_value ( & self , place : PlaceRef < ' _ > ) -> Option < ValueIndex > {
684+ self . value ( self . find_len ( place) ?)
685+ }
686+
680687 /// Iterate over all direct children.
681688 fn children ( & self , parent : PlaceIndex ) -> impl Iterator < Item = PlaceIndex > {
682689 Children :: new ( self , parent)
@@ -689,7 +696,7 @@ impl<'tcx> Map<'tcx> {
689696 ///
690697 /// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
691698 /// as such.
692- fn for_each_aliasing_place (
699+ pub fn for_each_aliasing_place (
693700 & self ,
694701 place : PlaceRef < ' _ > ,
695702 tail_elem : Option < TrackElem > ,
@@ -778,6 +785,31 @@ impl<'tcx> Map<'tcx> {
778785 }
779786 }
780787 }
788+
789+ /// Recursively iterates on each value contained in `target`, paired with matching projection
790+ /// inside `source`.
791+ pub fn for_each_value_pair (
792+ & self ,
793+ target : PlaceIndex ,
794+ source : PlaceIndex ,
795+ f : & mut impl FnMut ( ValueIndex , ValueIndex ) ,
796+ ) {
797+ // If both places are tracked, we copy the value to the target.
798+ // If the target is tracked, but the source is not, we do nothing, as invalidation has
799+ // already been performed.
800+ if let Some ( target_value) = self . places [ target] . value_index {
801+ if let Some ( source_value) = self . places [ source] . value_index {
802+ f ( target_value, source_value)
803+ }
804+ }
805+ for target_child in self . children ( target) {
806+ // Try to find corresponding child and recurse. Reasoning is similar as above.
807+ let projection = self . places [ target_child] . proj_elem . unwrap ( ) ;
808+ if let Some ( source_child) = self . projections . get ( & ( source, projection) ) {
809+ self . for_each_value_pair ( target_child, * source_child, f) ;
810+ }
811+ }
812+ }
781813}
782814
783815/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
0 commit comments