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