1 use rustc_index::bit_set::BitSet;
2 use rustc_middle::mir::{self, BasicBlock, Location};
4 use super::{Analysis, Direction, Results};
5 use crate::dataflow::impls::{borrows::Borrows, EverInitializedPlaces, MaybeUninitializedPlaces};
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>,
13 vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>,
15 V: ResultsVisitable<'tcx, FlowState = F>,
17 let mut state = results.new_flow_state(body);
19 #[cfg(debug_assertions)]
20 let reachable_blocks = mir::traversal::reachable_as_bitset(body);
23 #[cfg(debug_assertions)]
24 assert!(reachable_blocks.contains(block));
26 let block_data = &body[block];
27 V::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
31 pub trait ResultsVisitor<'mir, 'tcx> {
36 _state: &Self::FlowState,
37 _block_data: &'mir mir::BasicBlockData<'tcx>,
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(
46 _state: &Self::FlowState,
47 _statement: &'mir mir::Statement<'tcx>,
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(
56 _state: &Self::FlowState,
57 _statement: &'mir mir::Statement<'tcx>,
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(
66 _state: &Self::FlowState,
67 _terminator: &'mir mir::Terminator<'tcx>,
72 /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
73 /// terminator applied to `state`.
75 /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
76 fn visit_terminator_after_primary_effect(
78 _state: &Self::FlowState,
79 _terminator: &'mir mir::Terminator<'tcx>,
86 _state: &Self::FlowState,
87 _block_data: &'mir mir::BasicBlockData<'tcx>,
93 /// Things that can be visited by a `ResultsVisitor`.
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;
101 /// Creates an empty `FlowState` to hold the transient state for these dataflow results.
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;
107 fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock);
109 fn reconstruct_before_statement_effect(
111 state: &mut Self::FlowState,
112 statement: &mir::Statement<'tcx>,
116 fn reconstruct_statement_effect(
118 state: &mut Self::FlowState,
119 statement: &mir::Statement<'tcx>,
123 fn reconstruct_before_terminator_effect(
125 state: &mut Self::FlowState,
126 terminator: &mir::Terminator<'tcx>,
130 fn reconstruct_terminator_effect(
132 state: &mut Self::FlowState,
133 terminator: &mir::Terminator<'tcx>,
138 impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
142 type FlowState = BitSet<A::Idx>;
144 type Direction = A::Direction;
146 fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
147 BitSet::new_empty(self.analysis.bits_per_block(body))
150 fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
151 state.overwrite(&self.entry_set_for_block(block));
154 fn reconstruct_before_statement_effect(
156 state: &mut Self::FlowState,
157 stmt: &mir::Statement<'tcx>,
160 self.analysis.apply_before_statement_effect(state, stmt, loc);
163 fn reconstruct_statement_effect(
165 state: &mut Self::FlowState,
166 stmt: &mir::Statement<'tcx>,
169 self.analysis.apply_statement_effect(state, stmt, loc);
172 fn reconstruct_before_terminator_effect(
174 state: &mut Self::FlowState,
175 term: &mir::Terminator<'tcx>,
178 self.analysis.apply_before_terminator_effect(state, term, loc);
181 fn reconstruct_terminator_effect(
183 state: &mut Self::FlowState,
184 term: &mir::Terminator<'tcx>,
187 self.analysis.apply_terminator_effect(state, term, loc);
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.
194 pub struct BorrowckAnalyses<B, U, E> {
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>>,
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;
211 macro_rules! impl_visitable {
213 $T:ident { $( $field:ident : $A:ident ),* $(,)? }
215 impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
217 $( $A: Analysis<'tcx, Direction = D>, )*
220 type FlowState = $T<$( BitSet<$A::Idx> ),*>;
222 fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
224 $( $field: BitSet::new_empty(self.$field.analysis.bits_per_block(body)) ),*
228 fn reset_to_block_entry(
230 state: &mut Self::FlowState,
233 $( state.$field.overwrite(&self.$field.entry_set_for_block(block)); )*
236 fn reconstruct_before_statement_effect(
238 state: &mut Self::FlowState,
239 stmt: &mir::Statement<'tcx>,
242 $( self.$field.analysis
243 .apply_before_statement_effect(&mut state.$field, stmt, loc); )*
246 fn reconstruct_statement_effect(
248 state: &mut Self::FlowState,
249 stmt: &mir::Statement<'tcx>,
252 $( self.$field.analysis
253 .apply_statement_effect(&mut state.$field, stmt, loc); )*
256 fn reconstruct_before_terminator_effect(
258 state: &mut Self::FlowState,
259 term: &mir::Terminator<'tcx>,
262 $( self.$field.analysis
263 .apply_before_terminator_effect(&mut state.$field, term, loc); )*
266 fn reconstruct_terminator_effect(
268 state: &mut Self::FlowState,
269 term: &mir::Terminator<'tcx>,
272 $( self.$field.analysis
273 .apply_terminator_effect(&mut state.$field, term, loc); )*
280 BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }