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