@@ -950,3 +950,56 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
950950 }
951951 }
952952}
953+
954+ /// A depth-first search over the allocation graph.
955+ ///
956+ /// This is based on the DFS in `rustc_data_structures`, which we cannot use directly because
957+ /// `AllocId` does not implement `Idx`.
958+ pub struct DepthFirstSearch < ' mem , ' mir , ' tcx , M : Machine < ' mir , ' tcx > > {
959+ memory : & ' mem Memory < ' mir , ' tcx , M > ,
960+ visited : FxHashSet < AllocId > ,
961+ stack : Vec < AllocId > ,
962+ }
963+
964+ impl < M : Machine < ' mir , ' tcx > > DepthFirstSearch < ' mem , ' mir , ' tcx , M > {
965+ /// Returns a new DFS iterator that will traverse all allocations reachable from the given
966+ /// `AllocId`s.
967+ ///
968+ /// The first node in `roots` will be the first node visited by the DFS.
969+ pub fn with_roots (
970+ memory : & ' mem Memory < ' mir , ' tcx , M > ,
971+ roots : impl IntoIterator < Item = AllocId > ,
972+ ) -> Self {
973+ let mut stack: Vec < _ > = roots. into_iter ( ) . collect ( ) ;
974+ stack. reverse ( ) ;
975+
976+ DepthFirstSearch {
977+ memory,
978+ visited : stack. iter ( ) . copied ( ) . collect ( ) ,
979+ stack,
980+ }
981+ }
982+ }
983+
984+ impl < M : Machine < ' mir , ' tcx > > Iterator for DepthFirstSearch < ' mem , ' mir , ' tcx , M > {
985+ type Item = ( AllocId , InterpResult < ' tcx , & ' mem Allocation < M :: PointerTag , M :: AllocExtra > > ) ;
986+
987+ fn next ( & mut self ) -> Option < Self :: Item > {
988+ let DepthFirstSearch { stack, visited, memory } = self ;
989+
990+ let id = stack. pop ( ) ?;
991+ let alloc = memory. get_raw ( id) ;
992+
993+ if let Ok ( alloc) = alloc {
994+ let new_pointers = alloc
995+ . relocations ( )
996+ . values ( )
997+ . map ( |& ( _, id) | id)
998+ . filter ( |id| visited. insert ( * id) ) ;
999+
1000+ stack. extend ( new_pointers) ;
1001+ }
1002+
1003+ Some ( ( id, alloc) )
1004+ }
1005+ }
0 commit comments