@@ -344,6 +344,100 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> {
344344 fn body ( & self ) -> & ' a Body < ' tcx > ;
345345}
346346
347+ /// Allows iterating dataflow results in a flexible and reasonably fast way.
348+ #[ derive( Clone ) ]
349+ pub struct DataflowResultsCursor < ' mir , ' tcx , BD , DR >
350+ where
351+ BD : BitDenotation < ' tcx > ,
352+ DR : Borrow < DataflowResults < ' tcx , BD > > ,
353+ {
354+ flow_state : FlowAtLocation < ' tcx , BD , DR > ,
355+
356+ // The statement (or terminator) whose effect has been reconstructed in
357+ // flow_state.
358+ curr_loc : Option < Location > ,
359+
360+ body : & ' mir Body < ' tcx > ,
361+ }
362+
363+ pub type DataflowResultsRefCursor < ' mir , ' tcx , ' flow , BD > =
364+ DataflowResultsCursor < ' mir , ' tcx , BD , & ' flow DataflowResults < ' tcx , BD > > ;
365+
366+ impl < ' mir , ' tcx , BD , DR > DataflowResultsCursor < ' mir , ' tcx , BD , DR >
367+ where
368+ BD : BitDenotation < ' tcx > ,
369+ DR : Borrow < DataflowResults < ' tcx , BD > > ,
370+ {
371+ pub fn new ( result : DR , body : & ' mir Body < ' tcx > ) -> Self {
372+ DataflowResultsCursor {
373+ flow_state : FlowAtLocation :: new ( result) ,
374+ curr_loc : None ,
375+ body,
376+ }
377+ }
378+
379+ /// Seek to the given location in MIR. This method is fast if you are
380+ /// traversing your MIR statements in order.
381+ ///
382+ /// After calling `seek`, the current state will reflect all effects up to
383+ /// and including the `before_statement_effect` of the statement at location
384+ /// `loc`. The `statement_effect` of the statement at `loc` will be
385+ /// available as the current effect (see e.g. `each_gen_bit`).
386+ ///
387+ /// If `loc.statement_index` equals the number of statements in the block,
388+ /// we will reconstruct the terminator effect in the same way as described
389+ /// above.
390+ pub fn seek ( & mut self , loc : Location ) {
391+ if self . curr_loc . map ( |cur| loc == cur) . unwrap_or ( false ) {
392+ return ;
393+ }
394+
395+ let start_index;
396+ let should_reset = match self . curr_loc {
397+ None => true ,
398+ Some ( cur)
399+ if loc. block != cur. block || loc. statement_index < cur. statement_index => true ,
400+ _ => false ,
401+ } ;
402+ if should_reset {
403+ self . flow_state . reset_to_entry_of ( loc. block ) ;
404+ start_index = 0 ;
405+ } else {
406+ let curr_loc = self . curr_loc . unwrap ( ) ;
407+ start_index = curr_loc. statement_index ;
408+ // Apply the effect from the last seek to the current state.
409+ self . flow_state . apply_local_effect ( curr_loc) ;
410+ }
411+
412+ for stmt in start_index..loc. statement_index {
413+ let mut stmt_loc = loc;
414+ stmt_loc. statement_index = stmt;
415+ self . flow_state . reconstruct_statement_effect ( stmt_loc) ;
416+ self . flow_state . apply_local_effect ( stmt_loc) ;
417+ }
418+
419+ if loc. statement_index == self . body [ loc. block ] . statements . len ( ) {
420+ self . flow_state . reconstruct_terminator_effect ( loc) ;
421+ } else {
422+ self . flow_state . reconstruct_statement_effect ( loc) ;
423+ }
424+ self . curr_loc = Some ( loc) ;
425+ }
426+
427+ /// Return whether the current state contains bit `x`.
428+ pub fn contains ( & self , x : BD :: Idx ) -> bool {
429+ self . flow_state . contains ( x)
430+ }
431+
432+ /// Iterate over each `gen` bit in the current effect (invoke `seek` first).
433+ pub fn each_gen_bit < F > ( & self , f : F )
434+ where
435+ F : FnMut ( BD :: Idx ) ,
436+ {
437+ self . flow_state . each_gen_bit ( f)
438+ }
439+ }
440+
347441pub fn state_for_location < ' tcx , T : BitDenotation < ' tcx > > ( loc : Location ,
348442 analysis : & T ,
349443 result : & DataflowResults < ' tcx , T > ,
0 commit comments