@@ -188,10 +188,6 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
188188 }
189189}
190190
191- pub fn postorder < ' a , ' tcx > ( body : & ' a Body < ' tcx > ) -> Postorder < ' a , ' tcx > {
192- Postorder :: new ( & body. basic_blocks , START_BLOCK )
193- }
194-
195191impl < ' a , ' tcx > Iterator for Postorder < ' a , ' tcx > {
196192 type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
197193
@@ -219,6 +215,42 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
219215 }
220216}
221217
218+ /// Creates an iterator over the `Body`'s basic blocks, that:
219+ /// - returns basic blocks in a postorder,
220+ /// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
221+ /// postorder itself.
222+ pub fn postorder < ' a , ' tcx > ( body : & ' a Body < ' tcx > ) -> PostorderIter < ' a , ' tcx > {
223+ let blocks = body. basic_blocks . reverse_postorder ( ) ;
224+ let len = blocks. len ( ) ;
225+ PostorderIter { body, blocks, idx : len }
226+ }
227+
228+ #[ derive( Clone ) ]
229+ pub struct PostorderIter < ' a , ' tcx > {
230+ body : & ' a Body < ' tcx > ,
231+ blocks : & ' a [ BasicBlock ] ,
232+ idx : usize ,
233+ }
234+
235+ impl < ' a , ' tcx > Iterator for PostorderIter < ' a , ' tcx > {
236+ type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
237+
238+ fn next ( & mut self ) -> Option < ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > {
239+ if self . idx == 0 {
240+ return None ;
241+ }
242+ self . idx -= 1 ;
243+
244+ self . blocks . get ( self . idx ) . map ( |& bb| ( bb, & self . body [ bb] ) )
245+ }
246+
247+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
248+ ( self . idx , Some ( self . idx ) )
249+ }
250+ }
251+
252+ impl < ' a , ' tcx > ExactSizeIterator for PostorderIter < ' a , ' tcx > { }
253+
222254/// Reverse postorder traversal of a graph
223255///
224256/// Reverse postorder is the reverse order of a postorder traversal.
0 commit comments