@@ -344,6 +344,100 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> {
344
344
fn body ( & self ) -> & ' a Body < ' tcx > ;
345
345
}
346
346
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
+
347
441
pub fn state_for_location < ' tcx , T : BitDenotation < ' tcx > > ( loc : Location ,
348
442
analysis : & T ,
349
443
result : & DataflowResults < ' tcx , T > ,
0 commit comments