@@ -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 > ,
@@ -745,11 +750,15 @@ impl<'tcx> Map<'tcx> {
745
750
}
746
751
}
747
752
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
+
748
759
/// Invoke a function on each value in the given place and all descendants.
749
760
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) {
753
762
f ( v)
754
763
}
755
764
}
@@ -778,6 +787,31 @@ impl<'tcx> Map<'tcx> {
778
787
}
779
788
}
780
789
}
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
+ }
781
815
}
782
816
783
817
/// This is the information tracked for every [`PlaceIndex`] and is stored by [`Map`].
0 commit comments