@@ -26,7 +26,7 @@ rustc_index::newtype_index!(
26
26
/// This index uniquely identifies a tracked place and therefore a slot in [`State`].
27
27
///
28
28
/// It is an implementation detail of this module.
29
- struct ValueIndex { }
29
+ pub struct ValueIndex { }
30
30
) ;
31
31
32
32
/// See [`State`].
@@ -211,22 +211,9 @@ impl<V: Clone + HasBottom> State<V> {
211
211
/// The target place must have been flooded before calling this method.
212
212
pub fn insert_place_idx ( & mut self , target : PlaceIndex , source : PlaceIndex , map : & Map < ' _ > ) {
213
213
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
+ } ) ;
230
217
}
231
218
232
219
/// Helper method to interpret `target = result`.
@@ -677,6 +664,26 @@ impl<'tcx> Map<'tcx> {
677
664
self . find_extra ( place, [ TrackElem :: DerefLen ] )
678
665
}
679
666
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
+
680
687
/// Iterate over all direct children.
681
688
fn children ( & self , parent : PlaceIndex ) -> impl Iterator < Item = PlaceIndex > {
682
689
Children :: new ( self , parent)
@@ -689,7 +696,7 @@ impl<'tcx> Map<'tcx> {
689
696
///
690
697
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
691
698
/// as such.
692
- fn for_each_aliasing_place (
699
+ pub fn for_each_aliasing_place (
693
700
& self ,
694
701
place : PlaceRef < ' _ > ,
695
702
tail_elem : Option < TrackElem > ,
@@ -778,6 +785,31 @@ impl<'tcx> Map<'tcx> {
778
785
}
779
786
}
780
787
}
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
+ }
781
813
}
782
814
783
815
/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
0 commit comments