]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/flows.rs
Rollup merge of #61420 - felixrabe:patch-2, r=dtolnay
[rust.git] / src / librustc_mir / borrow_check / flows.rs
1 //! Manages the dataflow bits required for borrowck.
2 //!
3 //! FIXME: this might be better as a "generic" fixed-point combinator,
4 //! but is not as ugly as it is right now.
5
6 use rustc::mir::{BasicBlock, Location};
7 use rustc::ty::RegionVid;
8 use rustc_data_structures::bit_set::BitIter;
9
10 use crate::borrow_check::location::LocationIndex;
11
12 use polonius_engine::Output;
13
14 use crate::dataflow::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;
20 use either::Either;
21 use std::fmt;
22 use std::rc::Rc;
23
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>>,
29
30     /// Polonius Output
31     pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
32 }
33
34 impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
35     crate fn new(
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>>>,
40     ) -> Self {
41         Flows {
42             borrows,
43             uninits,
44             ever_inits,
45             polonius_output,
46         }
47     }
48
49     crate fn borrows_in_scope(
50         &self,
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())
55         } else {
56             Either::Right(self.borrows.iter_incoming())
57         }
58     }
59
60     crate fn with_outgoing_borrows(&self, op: impl FnOnce(BitIter<'_, BorrowIndex>)) {
61         self.borrows.with_iter_outgoing(op)
62     }
63 }
64
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);
70     };
71 }
72
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));
76     }
77
78     fn reset_to_exit_of(&mut self, bb: BasicBlock) {
79         each_flow!(self, reset_to_exit_of(bb));
80     }
81
82     fn reconstruct_statement_effect(&mut self, location: Location) {
83         each_flow!(self, reconstruct_statement_effect(location));
84     }
85
86     fn reconstruct_terminator_effect(&mut self, location: Location) {
87         each_flow!(self, reconstruct_terminator_effect(location));
88     }
89
90     fn apply_local_effect(&mut self, location: Location) {
91         each_flow!(self, apply_local_effect(location));
92     }
93 }
94
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();
98
99         s.push_str("borrows in effect: [");
100         let mut saw_one = false;
101         self.borrows.each_state_bit(|borrow| {
102             if saw_one {
103                 s.push_str(", ");
104             };
105             saw_one = true;
106             let borrow_data = &self.borrows.operator().borrows()[borrow];
107             s.push_str(&borrow_data.to_string());
108         });
109         s.push_str("] ");
110
111         s.push_str("borrows generated: [");
112         let mut saw_one = false;
113         self.borrows.each_gen_bit(|borrow| {
114             if saw_one {
115                 s.push_str(", ");
116             };
117             saw_one = true;
118             let borrow_data = &self.borrows.operator().borrows()[borrow];
119             s.push_str(&borrow_data.to_string());
120         });
121         s.push_str("] ");
122
123         s.push_str("uninits: [");
124         let mut saw_one = false;
125         self.uninits.each_state_bit(|mpi_uninit| {
126             if saw_one {
127                 s.push_str(", ");
128             };
129             saw_one = true;
130             let move_path = &self.uninits.operator().move_data().move_paths[mpi_uninit];
131             s.push_str(&move_path.to_string());
132         });
133         s.push_str("] ");
134
135         s.push_str("ever_init: [");
136         let mut saw_one = false;
137         self.ever_inits.each_state_bit(|mpi_ever_init| {
138             if saw_one {
139                 s.push_str(", ");
140             };
141             saw_one = true;
142             let ever_init = &self.ever_inits.operator().move_data().inits[mpi_ever_init];
143             s.push_str(&format!("{:?}", ever_init));
144         });
145         s.push_str("]");
146
147         fmt::Display::fmt(&s, fmt)
148     }
149 }