11//! Random access inspection of the results of a dataflow analysis.
22
3- use crate :: framework:: BitSetExt ;
3+ use crate :: { framework:: BitSetExt , CloneAnalysis } ;
44
5- use std:: borrow:: Borrow ;
5+ use std:: borrow:: { Borrow , BorrowMut } ;
66use std:: cmp:: Ordering ;
77
88#[ cfg( debug_assertions) ]
99use rustc_index:: bit_set:: BitSet ;
1010use rustc_middle:: mir:: { self , BasicBlock , Location } ;
1111
12- use super :: { Analysis , Direction , Effect , EffectIndex , Results } ;
12+ use super :: { Analysis , Direction , Effect , EffectIndex , EntrySets , Results , ResultsCloned } ;
13+
14+ // `AnalysisResults` is needed as an impl such as the following has an unconstrained type
15+ // parameter:
16+ // ```
17+ // impl<'tcx, A, E, R> ResultsCursor<'_, 'tcx, A, R>
18+ // where
19+ // A: Analysis<'tcx>,
20+ // E: Borrow<EntrySets<'tcx, A>>,
21+ // R: Results<'tcx, A, E>,
22+ // {}
23+ // ```
24+
25+ /// A type representing the analysis results consumed by a `ResultsCursor`.
26+ pub trait AnalysisResults < ' tcx , A > : BorrowMut < Results < ' tcx , A , Self :: EntrySets > >
27+ where
28+ A : Analysis < ' tcx > ,
29+ {
30+ /// The type containing the entry sets for this `Results` type.
31+ ///
32+ /// Should be either `EntrySets<'tcx, A>` or `&EntrySets<'tcx, A>`.
33+ type EntrySets : Borrow < EntrySets < ' tcx , A > > ;
34+ }
35+ impl < ' tcx , A , E > AnalysisResults < ' tcx , A > for Results < ' tcx , A , E >
36+ where
37+ A : Analysis < ' tcx > ,
38+ E : Borrow < EntrySets < ' tcx , A > > ,
39+ {
40+ type EntrySets = E ;
41+ }
42+ impl < ' a , ' tcx , A , E > AnalysisResults < ' tcx , A > for & ' a mut Results < ' tcx , A , E >
43+ where
44+ A : Analysis < ' tcx > ,
45+ E : Borrow < EntrySets < ' tcx , A > > ,
46+ {
47+ type EntrySets = E ;
48+ }
1349
1450/// A `ResultsCursor` that borrows the underlying `Results`.
15- pub type ResultsRefCursor < ' a , ' mir , ' tcx , A > = ResultsCursor < ' mir , ' tcx , A , & ' a Results < ' tcx , A > > ;
51+ pub type ResultsRefCursor < ' res , ' mir , ' tcx , A > =
52+ ResultsCursor < ' mir , ' tcx , A , & ' res mut Results < ' tcx , A > > ;
53+
54+ /// A `ResultsCursor` which uses a cloned `Analysis` while borrowing the underlying `Results`. This
55+ /// allows multiple cursors over the same `Results`.
56+ pub type ResultsClonedCursor < ' res , ' mir , ' tcx , A > =
57+ ResultsCursor < ' mir , ' tcx , A , ResultsCloned < ' res , ' tcx , A > > ;
1658
1759/// Allows random access inspection of the results of a dataflow analysis.
1860///
4587impl < ' mir , ' tcx , A , R > ResultsCursor < ' mir , ' tcx , A , R >
4688where
4789 A : Analysis < ' tcx > ,
48- R : Borrow < Results < ' tcx , A > > ,
90+ {
91+ /// Returns the dataflow state at the current location.
92+ pub fn get ( & self ) -> & A :: Domain {
93+ & self . state
94+ }
95+
96+ /// Returns the body this analysis was run on.
97+ pub fn body ( & self ) -> & ' mir mir:: Body < ' tcx > {
98+ self . body
99+ }
100+
101+ /// Unwraps this cursor, returning the underlying `Results`.
102+ pub fn into_results ( self ) -> R {
103+ self . results
104+ }
105+ }
106+
107+ impl < ' res , ' mir , ' tcx , A > ResultsCursor < ' mir , ' tcx , A , ResultsCloned < ' res , ' tcx , A > >
108+ where
109+ A : Analysis < ' tcx > + CloneAnalysis ,
110+ {
111+ /// Creates a new cursor over the same `Results`. Note that the cursor's position is *not*
112+ /// copied.
113+ pub fn new_cursor ( & self ) -> Self {
114+ Self :: new ( self . body , self . results . reclone_analysis ( ) )
115+ }
116+ }
117+
118+ impl < ' mir , ' tcx , A , R > ResultsCursor < ' mir , ' tcx , A , R >
119+ where
120+ A : Analysis < ' tcx > ,
121+ R : AnalysisResults < ' tcx , A > ,
49122{
50123 /// Returns a new cursor that can inspect `results`.
51124 pub fn new ( body : & ' mir mir:: Body < ' tcx > , results : R ) -> Self {
@@ -74,18 +147,28 @@ where
74147 }
75148
76149 /// Returns the underlying `Results`.
77- pub fn results ( & self ) -> & Results < ' tcx , A > {
78- & self . results . borrow ( )
150+ pub fn results ( & mut self ) -> & Results < ' tcx , A , R :: EntrySets > {
151+ self . results . borrow ( )
152+ }
153+
154+ /// Returns the underlying `Results`.
155+ pub fn mut_results ( & mut self ) -> & mut Results < ' tcx , A , R :: EntrySets > {
156+ self . results . borrow_mut ( )
79157 }
80158
81159 /// Returns the `Analysis` used to generate the underlying `Results`.
82160 pub fn analysis ( & self ) -> & A {
83161 & self . results . borrow ( ) . analysis
84162 }
85163
86- /// Returns the dataflow state at the current location.
87- pub fn get ( & self ) -> & A :: Domain {
88- & self . state
164+ /// Returns the `Analysis` used to generate the underlying `Results`.
165+ pub fn mut_analysis ( & mut self ) -> & mut A {
166+ & mut self . results . borrow_mut ( ) . analysis
167+ }
168+
169+ /// Returns both the dataflow state at the current location and the `Analysis`.
170+ pub fn get_with_analysis ( & mut self ) -> ( & A :: Domain , & mut A ) {
171+ ( & self . state , & mut self . results . borrow_mut ( ) . analysis )
89172 }
90173
91174 /// Resets the cursor to hold the entry set for the given basic block.
97180 #[ cfg( debug_assertions) ]
98181 assert ! ( self . reachable_blocks. contains( block) ) ;
99182
100- self . state . clone_from ( & self . results . borrow ( ) . entry_set_for_block ( block) ) ;
183+ self . state . clone_from ( self . results . borrow ( ) . entry_set_for_block ( block) ) ;
101184 self . pos = CursorPosition :: block_entry ( block) ;
102185 self . state_needs_reset = false ;
103186 }
@@ -186,7 +269,7 @@ where
186269 )
187270 } ;
188271
189- let analysis = & self . results . borrow ( ) . analysis ;
272+ let analysis = & mut self . results . borrow_mut ( ) . analysis ;
190273 let target_effect_index = effect. at_index ( target. statement_index ) ;
191274
192275 A :: Direction :: apply_effects_in_range (
@@ -205,8 +288,8 @@ where
205288 ///
206289 /// This can be used, e.g., to apply the call return effect directly to the cursor without
207290 /// creating an extra copy of the dataflow state.
208- pub fn apply_custom_effect ( & mut self , f : impl FnOnce ( & A , & mut A :: Domain ) ) {
209- f ( & self . results . borrow ( ) . analysis , & mut self . state ) ;
291+ pub fn apply_custom_effect ( & mut self , f : impl FnOnce ( & mut A , & mut A :: Domain ) ) {
292+ f ( & mut self . results . borrow_mut ( ) . analysis , & mut self . state ) ;
210293 self . state_needs_reset = true ;
211294 }
212295}
@@ -215,7 +298,6 @@ impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
215298where
216299 A : crate :: GenKillAnalysis < ' tcx > ,
217300 A :: Domain : BitSetExt < A :: Idx > ,
218- R : Borrow < Results < ' tcx , A > > ,
219301{
220302 pub fn contains ( & self , elem : A :: Idx ) -> bool {
221303 self . get ( ) . contains ( elem)
0 commit comments