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.
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.
11 //! Manages the dataflow bits required for borrowck.
13 //! FIXME: this might be better as a "generic" fixed-point combinator,
14 //! but is not as ugly as it is right now.
16 use rustc
::mir
::{BasicBlock, Location}
;
17 use rustc
::ty
::RegionVid
;
18 use rustc_data_structures
::bitvec
::BitIter
;
20 use borrow_check
::location
::LocationIndex
;
22 use polonius_engine
::Output
;
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
;
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
>>,
41 pub polonius_output
: Option
<Rc
<Output
<RegionVid
, BorrowIndex
, LocationIndex
>>>,
44 impl<'b
, 'gcx
, 'tcx
> Flows
<'b
, 'gcx
, 'tcx
> {
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
>>>,
59 crate fn borrows_in_scope(
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())
66 Either
::Right(self.borrows
.iter_incoming())
70 crate fn with_outgoing_borrows(&self, op
: impl FnOnce(BitIter
<BorrowIndex
>)) {
71 self.borrows
.with_iter_outgoing(op
)
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
);
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
));
88 fn reset_to_exit_of(&mut self, bb
: BasicBlock
) {
89 each_flow
!(self, reset_to_exit_of(bb
));
92 fn reconstruct_statement_effect(&mut self, location
: Location
) {
93 each_flow
!(self, reconstruct_statement_effect(location
));
96 fn reconstruct_terminator_effect(&mut self, location
: Location
) {
97 each_flow
!(self, reconstruct_terminator_effect(location
));
100 fn apply_local_effect(&mut self, location
: Location
) {
101 each_flow
!(self, apply_local_effect(location
));
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();
109 s
.push_str("borrows in effect: [");
110 let mut saw_one
= false;
111 self.borrows
.each_state_bit(|borrow
| {
116 let borrow_data
= &self.borrows
.operator().borrows()[borrow
];
117 s
.push_str(&borrow_data
.to_string());
121 s
.push_str("borrows generated: [");
122 let mut saw_one
= false;
123 self.borrows
.each_gen_bit(|borrow
| {
128 let borrow_data
= &self.borrows
.operator().borrows()[borrow
];
129 s
.push_str(&borrow_data
.to_string());
133 s
.push_str("uninits: [");
134 let mut saw_one
= false;
135 self.uninits
.each_state_bit(|mpi_uninit
| {
140 let move_path
= &self.uninits
.operator().move_data().move_paths
[mpi_uninit
];
141 s
.push_str(&move_path
.to_string());
145 s
.push_str("ever_init: [");
146 let mut saw_one
= false;
147 self.ever_inits
.each_state_bit(|mpi_ever_init
| {
152 let ever_init
= &self.ever_inits
.operator().move_data().inits
[mpi_ever_init
];
153 s
.push_str(&format
!("{:?}", ever_init
));
157 fmt
::Display
::fmt(&s
, fmt
)