1 //! Manages the dataflow bits required for borrowck.
3 //! FIXME: this might be better as a "generic" fixed-point combinator,
4 //! but is not as ugly as it is right now.
6 use rustc::mir::{BasicBlock, Location};
7 use rustc::ty::RegionVid;
8 use rustc_data_structures::bit_set::BitIter;
10 use crate::borrow_check::location::LocationIndex;
12 use polonius_engine::Output;
14 use crate::dataflow::move_paths::indexes::BorrowIndex;
15 use crate::dataflow::move_paths::HasMoveData;
16 use crate::dataflow::Borrows;
17 use crate::dataflow::EverInitializedPlaces;
18 use crate::dataflow::{FlowAtLocation, FlowsAtLocation};
19 use crate::dataflow::MaybeUninitializedPlaces;
24 // (forced to be `pub` due to its use as an associated type below.)
25 crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
26 borrows: FlowAtLocation<'tcx, Borrows<'b, 'gcx, 'tcx>>,
27 pub uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
28 pub ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'gcx, 'tcx>>,
31 pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
34 impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
36 borrows: FlowAtLocation<'tcx, Borrows<'b, 'gcx, 'tcx>>,
37 uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
38 ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'gcx, 'tcx>>,
39 polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
49 crate fn borrows_in_scope(
51 location: LocationIndex,
52 ) -> impl Iterator<Item = BorrowIndex> + '_ {
53 if let Some(ref polonius) = self.polonius_output {
54 Either::Left(polonius.errors_at(location).iter().cloned())
56 Either::Right(self.borrows.iter_incoming())
60 crate fn with_outgoing_borrows(&self, op: impl FnOnce(BitIter<'_, BorrowIndex>)) {
61 self.borrows.with_iter_outgoing(op)
65 macro_rules! each_flow {
66 ($this:ident, $meth:ident($arg:ident)) => {
67 FlowAtLocation::$meth(&mut $this.borrows, $arg);
68 FlowAtLocation::$meth(&mut $this.uninits, $arg);
69 FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
73 impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
74 fn reset_to_entry_of(&mut self, bb: BasicBlock) {
75 each_flow!(self, reset_to_entry_of(bb));
78 fn reset_to_exit_of(&mut self, bb: BasicBlock) {
79 each_flow!(self, reset_to_exit_of(bb));
82 fn reconstruct_statement_effect(&mut self, location: Location) {
83 each_flow!(self, reconstruct_statement_effect(location));
86 fn reconstruct_terminator_effect(&mut self, location: Location) {
87 each_flow!(self, reconstruct_terminator_effect(location));
90 fn apply_local_effect(&mut self, location: Location) {
91 each_flow!(self, apply_local_effect(location));
95 impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
96 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
97 let mut s = String::new();
99 s.push_str("borrows in effect: [");
100 let mut saw_one = false;
101 self.borrows.each_state_bit(|borrow| {
106 let borrow_data = &self.borrows.operator().borrows()[borrow];
107 s.push_str(&borrow_data.to_string());
111 s.push_str("borrows generated: [");
112 let mut saw_one = false;
113 self.borrows.each_gen_bit(|borrow| {
118 let borrow_data = &self.borrows.operator().borrows()[borrow];
119 s.push_str(&borrow_data.to_string());
123 s.push_str("uninits: [");
124 let mut saw_one = false;
125 self.uninits.each_state_bit(|mpi_uninit| {
130 let move_path = &self.uninits.operator().move_data().move_paths[mpi_uninit];
131 s.push_str(&move_path.to_string());
135 s.push_str("ever_init: [");
136 let mut saw_one = false;
137 self.ever_inits.each_state_bit(|mpi_ever_init| {
142 let ever_init = &self.ever_inits.operator().move_data().inits[mpi_ever_init];
143 s.push_str(&format!("{:?}", ever_init));
147 fmt::Display::fmt(&s, fmt)