@@ -24,9 +24,7 @@ rustc_index::newtype_index!(
24
24
25
25
rustc_index:: newtype_index!(
26
26
/// 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 { }
30
28
) ;
31
29
32
30
/// See [`State`].
@@ -211,22 +209,9 @@ impl<V: Clone + HasBottom> State<V> {
211
209
/// The target place must have been flooded before calling this method.
212
210
pub fn insert_place_idx ( & mut self , target : PlaceIndex , source : PlaceIndex , map : & Map < ' _ > ) {
213
211
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
+ } ) ;
230
215
}
231
216
232
217
/// Helper method to interpret `target = result`.
@@ -677,6 +662,26 @@ impl<'tcx> Map<'tcx> {
677
662
self . find_extra ( place, [ TrackElem :: DerefLen ] )
678
663
}
679
664
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
+
680
685
/// Iterate over all direct children.
681
686
fn children ( & self , parent : PlaceIndex ) -> impl Iterator < Item = PlaceIndex > {
682
687
Children :: new ( self , parent)
@@ -689,7 +694,7 @@ impl<'tcx> Map<'tcx> {
689
694
///
690
695
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
691
696
/// as such.
692
- fn for_each_aliasing_place (
697
+ pub fn for_each_aliasing_place (
693
698
& self ,
694
699
place : PlaceRef < ' _ > ,
695
700
tail_elem : Option < TrackElem > ,
@@ -778,6 +783,31 @@ impl<'tcx> Map<'tcx> {
778
783
}
779
784
}
780
785
}
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
+ }
781
811
}
782
812
783
813
/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
0 commit comments