]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir/src/dataflow/framework/visitor.rs
Rollup merge of #76060 - pickfire:patch-12, r=jyn514
[rust.git] / compiler / rustc_mir / src / dataflow / framework / visitor.rs
1 use rustc_index::bit_set::BitSet;
2 use rustc_middle::mir::{self, BasicBlock, Location};
3
4 use super::{Analysis, Direction, Results};
5 use crate::dataflow::impls::{borrows::Borrows, EverInitializedPlaces, MaybeUninitializedPlaces};
6
7 /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
8 /// dataflow state at that location.
9 pub fn visit_results<F, V>(
10     body: &'mir mir::Body<'tcx>,
11     blocks: impl IntoIterator<Item = BasicBlock>,
12     results: &V,
13     vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>,
14 ) where
15     V: ResultsVisitable<'tcx, FlowState = F>,
16 {
17     let mut state = results.new_flow_state(body);
18
19     #[cfg(debug_assertions)]
20     let reachable_blocks = mir::traversal::reachable_as_bitset(body);
21
22     for block in blocks {
23         #[cfg(debug_assertions)]
24         assert!(reachable_blocks.contains(block));
25
26         let block_data = &body[block];
27         V::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
28     }
29 }
30
31 pub trait ResultsVisitor<'mir, 'tcx> {
32     type FlowState;
33
34     fn visit_block_start(
35         &mut self,
36         _state: &Self::FlowState,
37         _block_data: &'mir mir::BasicBlockData<'tcx>,
38         _block: BasicBlock,
39     ) {
40     }
41
42     /// Called with the `before_statement_effect` of the given statement applied to `state` but not
43     /// its `statement_effect`.
44     fn visit_statement_before_primary_effect(
45         &mut self,
46         _state: &Self::FlowState,
47         _statement: &'mir mir::Statement<'tcx>,
48         _location: Location,
49     ) {
50     }
51
52     /// Called with both the `before_statement_effect` and the `statement_effect` of the given
53     /// statement applied to `state`.
54     fn visit_statement_after_primary_effect(
55         &mut self,
56         _state: &Self::FlowState,
57         _statement: &'mir mir::Statement<'tcx>,
58         _location: Location,
59     ) {
60     }
61
62     /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not
63     /// its `terminator_effect`.
64     fn visit_terminator_before_primary_effect(
65         &mut self,
66         _state: &Self::FlowState,
67         _terminator: &'mir mir::Terminator<'tcx>,
68         _location: Location,
69     ) {
70     }
71
72     /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
73     /// terminator applied to `state`.
74     ///
75     /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
76     fn visit_terminator_after_primary_effect(
77         &mut self,
78         _state: &Self::FlowState,
79         _terminator: &'mir mir::Terminator<'tcx>,
80         _location: Location,
81     ) {
82     }
83
84     fn visit_block_end(
85         &mut self,
86         _state: &Self::FlowState,
87         _block_data: &'mir mir::BasicBlockData<'tcx>,
88         _block: BasicBlock,
89     ) {
90     }
91 }
92
93 /// Things that can be visited by a `ResultsVisitor`.
94 ///
95 /// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously.
96 /// DO NOT IMPLEMENT MANUALLY. Instead, use the `impl_visitable` macro below.
97 pub trait ResultsVisitable<'tcx> {
98     type Direction: Direction;
99     type FlowState;
100
101     /// Creates an empty `FlowState` to hold the transient state for these dataflow results.
102     ///
103     /// The value of the newly created `FlowState` will be overwritten by `reset_to_block_entry`
104     /// before it can be observed by a `ResultsVisitor`.
105     fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState;
106
107     fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock);
108
109     fn reconstruct_before_statement_effect(
110         &self,
111         state: &mut Self::FlowState,
112         statement: &mir::Statement<'tcx>,
113         location: Location,
114     );
115
116     fn reconstruct_statement_effect(
117         &self,
118         state: &mut Self::FlowState,
119         statement: &mir::Statement<'tcx>,
120         location: Location,
121     );
122
123     fn reconstruct_before_terminator_effect(
124         &self,
125         state: &mut Self::FlowState,
126         terminator: &mir::Terminator<'tcx>,
127         location: Location,
128     );
129
130     fn reconstruct_terminator_effect(
131         &self,
132         state: &mut Self::FlowState,
133         terminator: &mir::Terminator<'tcx>,
134         location: Location,
135     );
136 }
137
138 impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
139 where
140     A: Analysis<'tcx>,
141 {
142     type FlowState = BitSet<A::Idx>;
143
144     type Direction = A::Direction;
145
146     fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
147         BitSet::new_empty(self.analysis.bits_per_block(body))
148     }
149
150     fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
151         state.overwrite(&self.entry_set_for_block(block));
152     }
153
154     fn reconstruct_before_statement_effect(
155         &self,
156         state: &mut Self::FlowState,
157         stmt: &mir::Statement<'tcx>,
158         loc: Location,
159     ) {
160         self.analysis.apply_before_statement_effect(state, stmt, loc);
161     }
162
163     fn reconstruct_statement_effect(
164         &self,
165         state: &mut Self::FlowState,
166         stmt: &mir::Statement<'tcx>,
167         loc: Location,
168     ) {
169         self.analysis.apply_statement_effect(state, stmt, loc);
170     }
171
172     fn reconstruct_before_terminator_effect(
173         &self,
174         state: &mut Self::FlowState,
175         term: &mir::Terminator<'tcx>,
176         loc: Location,
177     ) {
178         self.analysis.apply_before_terminator_effect(state, term, loc);
179     }
180
181     fn reconstruct_terminator_effect(
182         &self,
183         state: &mut Self::FlowState,
184         term: &mir::Terminator<'tcx>,
185         loc: Location,
186     ) {
187         self.analysis.apply_terminator_effect(state, term, loc);
188     }
189 }
190
191 /// A tuple with named fields that can hold either the results or the transient state of the
192 /// dataflow analyses used by the borrow checker.
193 #[derive(Debug)]
194 pub struct BorrowckAnalyses<B, U, E> {
195     pub borrows: B,
196     pub uninits: U,
197     pub ever_inits: E,
198 }
199
200 /// The results of the dataflow analyses used by the borrow checker.
201 pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
202     Results<'tcx, Borrows<'mir, 'tcx>>,
203     Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
204     Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
205 >;
206
207 /// The transient state of the dataflow analyses used by the borrow checker.
208 pub type BorrowckFlowState<'mir, 'tcx> =
209     <BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
210
211 macro_rules! impl_visitable {
212     ( $(
213         $T:ident { $( $field:ident : $A:ident ),* $(,)? }
214     )* ) => { $(
215         impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
216         where
217             $( $A: Analysis<'tcx, Direction = D>, )*
218         {
219             type Direction = D;
220             type FlowState = $T<$( BitSet<$A::Idx> ),*>;
221
222             fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
223                 $T {
224                     $( $field: BitSet::new_empty(self.$field.analysis.bits_per_block(body)) ),*
225                 }
226             }
227
228             fn reset_to_block_entry(
229                 &self,
230                 state: &mut Self::FlowState,
231                 block: BasicBlock,
232             ) {
233                 $( state.$field.overwrite(&self.$field.entry_set_for_block(block)); )*
234             }
235
236             fn reconstruct_before_statement_effect(
237                 &self,
238                 state: &mut Self::FlowState,
239                 stmt: &mir::Statement<'tcx>,
240                 loc: Location,
241             ) {
242                 $( self.$field.analysis
243                     .apply_before_statement_effect(&mut state.$field, stmt, loc); )*
244             }
245
246             fn reconstruct_statement_effect(
247                 &self,
248                 state: &mut Self::FlowState,
249                 stmt: &mir::Statement<'tcx>,
250                 loc: Location,
251             ) {
252                 $( self.$field.analysis
253                     .apply_statement_effect(&mut state.$field, stmt, loc); )*
254             }
255
256             fn reconstruct_before_terminator_effect(
257                 &self,
258                 state: &mut Self::FlowState,
259                 term: &mir::Terminator<'tcx>,
260                 loc: Location,
261             ) {
262                 $( self.$field.analysis
263                     .apply_before_terminator_effect(&mut state.$field, term, loc); )*
264             }
265
266             fn reconstruct_terminator_effect(
267                 &self,
268                 state: &mut Self::FlowState,
269                 term: &mir::Terminator<'tcx>,
270                 loc: Location,
271             ) {
272                 $( self.$field.analysis
273                     .apply_terminator_effect(&mut state.$field, term, loc); )*
274             }
275         }
276     )* }
277 }
278
279 impl_visitable! {
280     BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
281 }