@@ -24,9 +24,7 @@ rustc_index::newtype_index!(
2424
2525rustc_index:: newtype_index!(
2626 /// This index uniquely identifies a tracked place and therefore a slot in [`State`].
27- ///
28- /// It is an implementation detail of this module.
29- struct ValueIndex { }
27+ pub struct ValueIndex { }
3028) ;
3129
3230/// See [`State`].
@@ -211,22 +209,9 @@ impl<V: Clone + HasBottom> State<V> {
211209 /// The target place must have been flooded before calling this method.
212210 pub fn insert_place_idx ( & mut self , target : PlaceIndex , source : PlaceIndex , map : & Map < ' _ > ) {
213211 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- && let Some ( source_value) = map. places [ source] . value_index
220- {
221- values. insert ( target_value, values. get ( source_value) . clone ( ) ) ;
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- }
212+ map. for_each_value_pair ( target, source, & mut |target, source| {
213+ values. insert ( target, values. get ( source) . clone ( ) ) ;
214+ } ) ;
230215 }
231216
232217 /// Helper method to interpret `target = result`.
@@ -677,6 +662,26 @@ impl<'tcx> Map<'tcx> {
677662 self . find_extra ( place, [ TrackElem :: DerefLen ] )
678663 }
679664
665+ /// Locates the value corresponding to the given place.
666+ pub fn value ( & self , place : PlaceIndex ) -> Option < ValueIndex > {
667+ self . places [ place] . value_index
668+ }
669+
670+ /// Locates the value corresponding to the given place.
671+ pub fn find_value ( & self , place : PlaceRef < ' _ > ) -> Option < ValueIndex > {
672+ self . value ( self . find ( place) ?)
673+ }
674+
675+ /// Locates the value corresponding to the given discriminant.
676+ pub fn find_discr_value ( & self , place : PlaceRef < ' _ > ) -> Option < ValueIndex > {
677+ self . value ( self . find_discr ( place) ?)
678+ }
679+
680+ /// Locates the value corresponding to the given length.
681+ pub fn find_len_value ( & self , place : PlaceRef < ' _ > ) -> Option < ValueIndex > {
682+ self . value ( self . find_len ( place) ?)
683+ }
684+
680685 /// Iterate over all direct children.
681686 fn children ( & self , parent : PlaceIndex ) -> impl Iterator < Item = PlaceIndex > {
682687 Children :: new ( self , parent)
@@ -689,7 +694,7 @@ impl<'tcx> Map<'tcx> {
689694 ///
690695 /// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
691696 /// as such.
692- fn for_each_aliasing_place (
697+ pub fn for_each_aliasing_place (
693698 & self ,
694699 place : PlaceRef < ' _ > ,
695700 tail_elem : Option < TrackElem > ,
@@ -778,6 +783,31 @@ impl<'tcx> Map<'tcx> {
778783 }
779784 }
780785 }
786+
787+ /// Recursively iterates on each value contained in `target`, paired with matching projection
788+ /// inside `source`.
789+ pub fn for_each_value_pair (
790+ & self ,
791+ target : PlaceIndex ,
792+ source : PlaceIndex ,
793+ f : & mut impl FnMut ( ValueIndex , ValueIndex ) ,
794+ ) {
795+ // If both places are tracked, we copy the value to the target.
796+ // If the target is tracked, but the source is not, we do nothing, as invalidation has
797+ // already been performed.
798+ if let Some ( target_value) = self . places [ target] . value_index
799+ && let Some ( source_value) = self . places [ source] . value_index
800+ {
801+ f ( target_value, source_value)
802+ }
803+ for target_child in self . children ( target) {
804+ // Try to find corresponding child and recurse. Reasoning is similar as above.
805+ let projection = self . places [ target_child] . proj_elem . unwrap ( ) ;
806+ if let Some ( source_child) = self . projections . get ( & ( source, projection) ) {
807+ self . for_each_value_pair ( target_child, * source_child, f) ;
808+ }
809+ }
810+ }
781811}
782812
783813/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
0 commit comments