]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/flows.rs
Omit 'missing IndexMut impl' suggestion when IndexMut is implemented.
[rust.git] / src / librustc_mir / borrow_check / flows.rs
1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Manages the dataflow bits required for borrowck.
12 //!
13 //! FIXME: this might be better as a "generic" fixed-point combinator,
14 //! but is not as ugly as it is right now.
15
16 use rustc::mir::{BasicBlock, Location};
17 use rustc::ty::RegionVid;
18 use rustc_data_structures::indexed_set::Iter;
19
20 use borrow_check::location::LocationIndex;
21
22 use polonius_engine::Output;
23
24 use dataflow::move_paths::indexes::BorrowIndex;
25 use dataflow::move_paths::HasMoveData;
26 use dataflow::Borrows;
27 use dataflow::{EverInitializedPlaces, MovingOutStatements};
28 use dataflow::{FlowAtLocation, FlowsAtLocation};
29 use dataflow::MaybeUninitializedPlaces;
30 use either::Either;
31 use std::fmt;
32 use std::rc::Rc;
33
34 // (forced to be `pub` due to its use as an associated type below.)
35 crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
36     borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
37     pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
38     pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
39     pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
40
41     /// Polonius Output
42     pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
43 }
44
45 impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
46     crate fn new(
47         borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
48         uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
49         move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
50         ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
51         polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
52     ) -> Self {
53         Flows {
54             borrows,
55             uninits,
56             move_outs,
57             ever_inits,
58             polonius_output,
59         }
60     }
61
62     crate fn borrows_in_scope(
63         &self,
64         location: LocationIndex,
65     ) -> impl Iterator<Item = BorrowIndex> + '_ {
66         if let Some(ref polonius) = self.polonius_output {
67             Either::Left(polonius.errors_at(location).iter().cloned())
68         } else {
69             Either::Right(self.borrows.iter_incoming())
70         }
71     }
72
73     crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter<BorrowIndex>)) {
74         self.borrows.with_iter_outgoing(op)
75     }
76 }
77
78 macro_rules! each_flow {
79     ($this:ident, $meth:ident($arg:ident)) => {
80         FlowAtLocation::$meth(&mut $this.borrows, $arg);
81         FlowAtLocation::$meth(&mut $this.uninits, $arg);
82         FlowAtLocation::$meth(&mut $this.move_outs, $arg);
83         FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
84     };
85 }
86
87 impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
88     fn reset_to_entry_of(&mut self, bb: BasicBlock) {
89         each_flow!(self, reset_to_entry_of(bb));
90     }
91
92     fn reset_to_exit_of(&mut self, bb: BasicBlock) {
93         each_flow!(self, reset_to_exit_of(bb));
94     }
95
96     fn reconstruct_statement_effect(&mut self, location: Location) {
97         each_flow!(self, reconstruct_statement_effect(location));
98     }
99
100     fn reconstruct_terminator_effect(&mut self, location: Location) {
101         each_flow!(self, reconstruct_terminator_effect(location));
102     }
103
104     fn apply_local_effect(&mut self, location: Location) {
105         each_flow!(self, apply_local_effect(location));
106     }
107 }
108
109 impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
110     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
111         let mut s = String::new();
112
113         s.push_str("borrows in effect: [");
114         let mut saw_one = false;
115         self.borrows.each_state_bit(|borrow| {
116             if saw_one {
117                 s.push_str(", ");
118             };
119             saw_one = true;
120             let borrow_data = &self.borrows.operator().borrows()[borrow];
121             s.push_str(&borrow_data.to_string());
122         });
123         s.push_str("] ");
124
125         s.push_str("borrows generated: [");
126         let mut saw_one = false;
127         self.borrows.each_gen_bit(|borrow| {
128             if saw_one {
129                 s.push_str(", ");
130             };
131             saw_one = true;
132             let borrow_data = &self.borrows.operator().borrows()[borrow];
133             s.push_str(&borrow_data.to_string());
134         });
135         s.push_str("] ");
136
137         s.push_str("uninits: [");
138         let mut saw_one = false;
139         self.uninits.each_state_bit(|mpi_uninit| {
140             if saw_one {
141                 s.push_str(", ");
142             };
143             saw_one = true;
144             let move_path = &self.uninits.operator().move_data().move_paths[mpi_uninit];
145             s.push_str(&move_path.to_string());
146         });
147         s.push_str("] ");
148
149         s.push_str("move_out: [");
150         let mut saw_one = false;
151         self.move_outs.each_state_bit(|mpi_move_out| {
152             if saw_one {
153                 s.push_str(", ");
154             };
155             saw_one = true;
156             let move_out = &self.move_outs.operator().move_data().moves[mpi_move_out];
157             s.push_str(&format!("{:?}", move_out));
158         });
159         s.push_str("] ");
160
161         s.push_str("ever_init: [");
162         let mut saw_one = false;
163         self.ever_inits.each_state_bit(|mpi_ever_init| {
164             if saw_one {
165                 s.push_str(", ");
166             };
167             saw_one = true;
168             let ever_init = &self.ever_inits.operator().move_data().inits[mpi_ever_init];
169             s.push_str(&format!("{:?}", ever_init));
170         });
171         s.push_str("]");
172
173         fmt::Display::fmt(&s, fmt)
174     }
175 }