@@ -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 > ,
@@ -745,11 +750,15 @@ impl<'tcx> Map<'tcx> {
745750 }
746751 }
747752
753+ /// Return the range of value indices inside this place.
754+ pub fn values_inside ( & self , root : PlaceIndex ) -> & [ ValueIndex ] {
755+ let range = self . inner_values [ root] . clone ( ) ;
756+ & self . inner_values_buffer [ range]
757+ }
758+
748759 /// Invoke a function on each value in the given place and all descendants.
749760 fn for_each_value_inside ( & self , root : PlaceIndex , f : & mut impl FnMut ( ValueIndex ) ) {
750- let range = self . inner_values [ root] . clone ( ) ;
751- let values = & self . inner_values_buffer [ range] ;
752- for & v in values {
761+ for & v in self . values_inside ( root) {
753762 f ( v)
754763 }
755764 }
@@ -778,6 +787,31 @@ impl<'tcx> Map<'tcx> {
778787 }
779788 }
780789 }
790+
791+ /// Recursively iterates on each value contained in `target`, paired with matching projection
792+ /// inside `source`.
793+ pub fn for_each_value_pair (
794+ & self ,
795+ target : PlaceIndex ,
796+ source : PlaceIndex ,
797+ f : & mut impl FnMut ( ValueIndex , ValueIndex ) ,
798+ ) {
799+ // If both places are tracked, we copy the value to the target.
800+ // If the target is tracked, but the source is not, we do nothing, as invalidation has
801+ // already been performed.
802+ if let Some ( target_value) = self . places [ target] . value_index
803+ && let Some ( source_value) = self . places [ source] . value_index
804+ {
805+ f ( target_value, source_value)
806+ }
807+ for target_child in self . children ( target) {
808+ // Try to find corresponding child and recurse. Reasoning is similar as above.
809+ let projection = self . places [ target_child] . proj_elem . unwrap ( ) ;
810+ if let Some ( source_child) = self . projections . get ( & ( source, projection) ) {
811+ self . for_each_value_pair ( target_child, * source_child, f) ;
812+ }
813+ }
814+ }
781815}
782816
783817/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
0 commit comments