1
1
//! Random access inspection of the results of a dataflow analysis.
2
2
3
- use crate :: framework:: BitSetExt ;
3
+ use crate :: { framework:: BitSetExt , CloneAnalysis } ;
4
4
5
- use std:: borrow:: Borrow ;
5
+ use std:: borrow:: { Borrow , BorrowMut } ;
6
6
use std:: cmp:: Ordering ;
7
7
8
8
#[ cfg( debug_assertions) ]
9
9
use rustc_index:: bit_set:: BitSet ;
10
10
use rustc_middle:: mir:: { self , BasicBlock , Location } ;
11
11
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
+ }
13
49
14
50
/// 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 > > ;
16
58
17
59
/// Allows random access inspection of the results of a dataflow analysis.
18
60
///
45
87
impl < ' mir , ' tcx , A , R > ResultsCursor < ' mir , ' tcx , A , R >
46
88
where
47
89
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 > ,
49
122
{
50
123
/// Returns a new cursor that can inspect `results`.
51
124
pub fn new ( body : & ' mir mir:: Body < ' tcx > , results : R ) -> Self {
@@ -74,18 +147,28 @@ where
74
147
}
75
148
76
149
/// 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 ( )
79
157
}
80
158
81
159
/// Returns the `Analysis` used to generate the underlying `Results`.
82
160
pub fn analysis ( & self ) -> & A {
83
161
& self . results . borrow ( ) . analysis
84
162
}
85
163
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 )
89
172
}
90
173
91
174
/// Resets the cursor to hold the entry set for the given basic block.
97
180
#[ cfg( debug_assertions) ]
98
181
assert ! ( self . reachable_blocks. contains( block) ) ;
99
182
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) ) ;
101
184
self . pos = CursorPosition :: block_entry ( block) ;
102
185
self . state_needs_reset = false ;
103
186
}
@@ -186,7 +269,7 @@ where
186
269
)
187
270
} ;
188
271
189
- let analysis = & self . results . borrow ( ) . analysis ;
272
+ let analysis = & mut self . results . borrow_mut ( ) . analysis ;
190
273
let target_effect_index = effect. at_index ( target. statement_index ) ;
191
274
192
275
A :: Direction :: apply_effects_in_range (
@@ -205,8 +288,8 @@ where
205
288
///
206
289
/// This can be used, e.g., to apply the call return effect directly to the cursor without
207
290
/// 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 ) ;
210
293
self . state_needs_reset = true ;
211
294
}
212
295
}
@@ -215,7 +298,6 @@ impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R>
215
298
where
216
299
A : crate :: GenKillAnalysis < ' tcx > ,
217
300
A :: Domain : BitSetExt < A :: Idx > ,
218
- R : Borrow < Results < ' tcx , A > > ,
219
301
{
220
302
pub fn contains ( & self , elem : A :: Idx ) -> bool {
221
303
self . get ( ) . contains ( elem)
0 commit comments