1 use rustc_middle::mir::{self, BasicBlock, Location};
3 use super::{Analysis, Direction, Results};
4 use crate::dataflow::impls::{borrows::Borrows, EverInitializedPlaces, MaybeUninitializedPlaces};
6 /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
7 /// dataflow state at that location.
8 pub fn visit_results<F, V>(
9 body: &'mir mir::Body<'tcx>,
10 blocks: impl IntoIterator<Item = BasicBlock>,
12 vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>,
14 V: ResultsVisitable<'tcx, FlowState = F>,
16 let mut state = results.new_flow_state(body);
18 #[cfg(debug_assertions)]
19 let reachable_blocks = mir::traversal::reachable_as_bitset(body);
22 #[cfg(debug_assertions)]
23 assert!(reachable_blocks.contains(block));
25 let block_data = &body[block];
26 V::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
30 pub trait ResultsVisitor<'mir, 'tcx> {
35 _state: &Self::FlowState,
36 _block_data: &'mir mir::BasicBlockData<'tcx>,
41 /// Called with the `before_statement_effect` of the given statement applied to `state` but not
42 /// its `statement_effect`.
43 fn visit_statement_before_primary_effect(
45 _state: &Self::FlowState,
46 _statement: &'mir mir::Statement<'tcx>,
51 /// Called with both the `before_statement_effect` and the `statement_effect` of the given
52 /// statement applied to `state`.
53 fn visit_statement_after_primary_effect(
55 _state: &Self::FlowState,
56 _statement: &'mir mir::Statement<'tcx>,
61 /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not
62 /// its `terminator_effect`.
63 fn visit_terminator_before_primary_effect(
65 _state: &Self::FlowState,
66 _terminator: &'mir mir::Terminator<'tcx>,
71 /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
72 /// terminator applied to `state`.
74 /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
75 fn visit_terminator_after_primary_effect(
77 _state: &Self::FlowState,
78 _terminator: &'mir mir::Terminator<'tcx>,
85 _state: &Self::FlowState,
86 _block_data: &'mir mir::BasicBlockData<'tcx>,
92 /// Things that can be visited by a `ResultsVisitor`.
94 /// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously.
95 /// DO NOT IMPLEMENT MANUALLY. Instead, use the `impl_visitable` macro below.
96 pub trait ResultsVisitable<'tcx> {
97 type Direction: Direction;
100 /// Creates an empty `FlowState` to hold the transient state for these dataflow results.
102 /// The value of the newly created `FlowState` will be overwritten by `reset_to_block_entry`
103 /// before it can be observed by a `ResultsVisitor`.
104 fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState;
106 fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock);
108 fn reconstruct_before_statement_effect(
110 state: &mut Self::FlowState,
111 statement: &mir::Statement<'tcx>,
115 fn reconstruct_statement_effect(
117 state: &mut Self::FlowState,
118 statement: &mir::Statement<'tcx>,
122 fn reconstruct_before_terminator_effect(
124 state: &mut Self::FlowState,
125 terminator: &mir::Terminator<'tcx>,
129 fn reconstruct_terminator_effect(
131 state: &mut Self::FlowState,
132 terminator: &mir::Terminator<'tcx>,
137 impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
141 type FlowState = A::Domain;
143 type Direction = A::Direction;
145 fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
146 self.analysis.bottom_value(body)
149 fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
150 state.clone_from(&self.entry_set_for_block(block));
153 fn reconstruct_before_statement_effect(
155 state: &mut Self::FlowState,
156 stmt: &mir::Statement<'tcx>,
159 self.analysis.apply_before_statement_effect(state, stmt, loc);
162 fn reconstruct_statement_effect(
164 state: &mut Self::FlowState,
165 stmt: &mir::Statement<'tcx>,
168 self.analysis.apply_statement_effect(state, stmt, loc);
171 fn reconstruct_before_terminator_effect(
173 state: &mut Self::FlowState,
174 term: &mir::Terminator<'tcx>,
177 self.analysis.apply_before_terminator_effect(state, term, loc);
180 fn reconstruct_terminator_effect(
182 state: &mut Self::FlowState,
183 term: &mir::Terminator<'tcx>,
186 self.analysis.apply_terminator_effect(state, term, loc);
190 /// A tuple with named fields that can hold either the results or the transient state of the
191 /// dataflow analyses used by the borrow checker.
193 pub struct BorrowckAnalyses<B, U, E> {
199 /// The results of the dataflow analyses used by the borrow checker.
200 pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
201 Results<'tcx, Borrows<'mir, 'tcx>>,
202 Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
203 Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
206 /// The transient state of the dataflow analyses used by the borrow checker.
207 pub type BorrowckFlowState<'mir, 'tcx> =
208 <BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
210 macro_rules! impl_visitable {
212 $T:ident { $( $field:ident : $A:ident ),* $(,)? }
214 impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
216 $( $A: Analysis<'tcx, Direction = D>, )*
219 type FlowState = $T<$( $A::Domain ),*>;
221 fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
223 $( $field: self.$field.analysis.bottom_value(body) ),*
227 fn reset_to_block_entry(
229 state: &mut Self::FlowState,
232 $( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )*
235 fn reconstruct_before_statement_effect(
237 state: &mut Self::FlowState,
238 stmt: &mir::Statement<'tcx>,
241 $( self.$field.analysis
242 .apply_before_statement_effect(&mut state.$field, stmt, loc); )*
245 fn reconstruct_statement_effect(
247 state: &mut Self::FlowState,
248 stmt: &mir::Statement<'tcx>,
251 $( self.$field.analysis
252 .apply_statement_effect(&mut state.$field, stmt, loc); )*
255 fn reconstruct_before_terminator_effect(
257 state: &mut Self::FlowState,
258 term: &mir::Terminator<'tcx>,
261 $( self.$field.analysis
262 .apply_before_terminator_effect(&mut state.$field, term, loc); )*
265 fn reconstruct_terminator_effect(
267 state: &mut Self::FlowState,
268 term: &mir::Terminator<'tcx>,
271 $( self.$field.analysis
272 .apply_terminator_effect(&mut state.$field, term, loc); )*
279 BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }