]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/borrow_check/flows.rs
New upstream version 1.38.0+dfsg1
[rustc.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, Local, 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::MaybeUninitializedPlaces;
19 use crate::dataflow::{FlowAtLocation, FlowsAtLocation};
20 use either::Either;
21 use std::fmt;
22 use std::rc::Rc;
23
24 crate type PoloniusOutput = Output<RegionVid, BorrowIndex, LocationIndex, Local>;
25
26 // (forced to be `pub` due to its use as an associated type below.)
27 crate struct Flows<'b, 'tcx> {
28 borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
29 pub uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'tcx>>,
30 pub ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'tcx>>,
31
32 /// Polonius Output
33 pub polonius_output: Option<Rc<PoloniusOutput>>,
34 }
35
36 impl<'b, 'tcx> Flows<'b, 'tcx> {
37 crate fn new(
38 borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
39 uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'tcx>>,
40 ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'tcx>>,
41 polonius_output: Option<Rc<PoloniusOutput>>,
42 ) -> Self {
43 Flows { borrows, uninits, ever_inits, polonius_output }
44 }
45
46 crate fn borrows_in_scope(
47 &self,
48 location: LocationIndex,
49 ) -> impl Iterator<Item = BorrowIndex> + '_ {
50 if let Some(ref polonius) = self.polonius_output {
51 Either::Left(polonius.errors_at(location).iter().cloned())
52 } else {
53 Either::Right(self.borrows.iter_incoming())
54 }
55 }
56
57 crate fn with_outgoing_borrows(&self, op: impl FnOnce(BitIter<'_, BorrowIndex>)) {
58 self.borrows.with_iter_outgoing(op)
59 }
60 }
61
62 macro_rules! each_flow {
63 ($this:ident, $meth:ident($arg:ident)) => {
64 FlowAtLocation::$meth(&mut $this.borrows, $arg);
65 FlowAtLocation::$meth(&mut $this.uninits, $arg);
66 FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
67 };
68 }
69
70 impl<'b, 'tcx> FlowsAtLocation for Flows<'b, 'tcx> {
71 fn reset_to_entry_of(&mut self, bb: BasicBlock) {
72 each_flow!(self, reset_to_entry_of(bb));
73 }
74
75 fn reset_to_exit_of(&mut self, bb: BasicBlock) {
76 each_flow!(self, reset_to_exit_of(bb));
77 }
78
79 fn reconstruct_statement_effect(&mut self, location: Location) {
80 each_flow!(self, reconstruct_statement_effect(location));
81 }
82
83 fn reconstruct_terminator_effect(&mut self, location: Location) {
84 each_flow!(self, reconstruct_terminator_effect(location));
85 }
86
87 fn apply_local_effect(&mut self, location: Location) {
88 each_flow!(self, apply_local_effect(location));
89 }
90 }
91
92 impl<'b, 'tcx> fmt::Display for Flows<'b, 'tcx> {
93 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
94 let mut s = String::new();
95
96 s.push_str("borrows in effect: [");
97 let mut saw_one = false;
98 self.borrows.each_state_bit(|borrow| {
99 if saw_one {
100 s.push_str(", ");
101 };
102 saw_one = true;
103 let borrow_data = &self.borrows.operator().borrows()[borrow];
104 s.push_str(&borrow_data.to_string());
105 });
106 s.push_str("] ");
107
108 s.push_str("borrows generated: [");
109 let mut saw_one = false;
110 self.borrows.each_gen_bit(|borrow| {
111 if saw_one {
112 s.push_str(", ");
113 };
114 saw_one = true;
115 let borrow_data = &self.borrows.operator().borrows()[borrow];
116 s.push_str(&borrow_data.to_string());
117 });
118 s.push_str("] ");
119
120 s.push_str("uninits: [");
121 let mut saw_one = false;
122 self.uninits.each_state_bit(|mpi_uninit| {
123 if saw_one {
124 s.push_str(", ");
125 };
126 saw_one = true;
127 let move_path = &self.uninits.operator().move_data().move_paths[mpi_uninit];
128 s.push_str(&move_path.to_string());
129 });
130 s.push_str("] ");
131
132 s.push_str("ever_init: [");
133 let mut saw_one = false;
134 self.ever_inits.each_state_bit(|mpi_ever_init| {
135 if saw_one {
136 s.push_str(", ");
137 };
138 saw_one = true;
139 let ever_init = &self.ever_inits.operator().move_data().inits[mpi_ever_init];
140 s.push_str(&format!("{:?}", ever_init));
141 });
142 s.push_str("]");
143
144 fmt::Display::fmt(&s, fmt)
145 }
146 }