1 //! Manages the dataflow bits required for borrowck.
3 //! FIXME: this might be better as a "generic" fixed-point combinator,
4 //! but is not as ugly as it is right now.
6 use rustc
::mir
::{BasicBlock, Local, Location}
;
7 use rustc
::ty
::RegionVid
;
8 use rustc_data_structures
::bit_set
::BitIter
;
10 use crate::borrow_check
::location
::LocationIndex
;
12 use polonius_engine
::Output
;
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}
;
24 crate type PoloniusOutput
= Output
<RegionVid
, BorrowIndex
, LocationIndex
, Local
>;
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
>>,
33 pub polonius_output
: Option
<Rc
<PoloniusOutput
>>,
36 impl<'b
, 'tcx
> Flows
<'b
, 'tcx
> {
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
>>,
43 Flows { borrows, uninits, ever_inits, polonius_output }
46 crate fn borrows_in_scope(
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())
53 Either
::Right(self.borrows
.iter_incoming())
57 crate fn with_outgoing_borrows(&self, op
: impl FnOnce(BitIter
<'_
, BorrowIndex
>)) {
58 self.borrows
.with_iter_outgoing(op
)
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
);
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
));
75 fn reset_to_exit_of(&mut self, bb
: BasicBlock
) {
76 each_flow
!(self, reset_to_exit_of(bb
));
79 fn reconstruct_statement_effect(&mut self, location
: Location
) {
80 each_flow
!(self, reconstruct_statement_effect(location
));
83 fn reconstruct_terminator_effect(&mut self, location
: Location
) {
84 each_flow
!(self, reconstruct_terminator_effect(location
));
87 fn apply_local_effect(&mut self, location
: Location
) {
88 each_flow
!(self, apply_local_effect(location
));
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();
96 s
.push_str("borrows in effect: [");
97 let mut saw_one
= false;
98 self.borrows
.each_state_bit(|borrow
| {
103 let borrow_data
= &self.borrows
.operator().borrows()[borrow
];
104 s
.push_str(&borrow_data
.to_string());
108 s
.push_str("borrows generated: [");
109 let mut saw_one
= false;
110 self.borrows
.each_gen_bit(|borrow
| {
115 let borrow_data
= &self.borrows
.operator().borrows()[borrow
];
116 s
.push_str(&borrow_data
.to_string());
120 s
.push_str("uninits: [");
121 let mut saw_one
= false;
122 self.uninits
.each_state_bit(|mpi_uninit
| {
127 let move_path
= &self.uninits
.operator().move_data().move_paths
[mpi_uninit
];
128 s
.push_str(&move_path
.to_string());
132 s
.push_str("ever_init: [");
133 let mut saw_one
= false;
134 self.ever_inits
.each_state_bit(|mpi_ever_init
| {
139 let ever_init
= &self.ever_inits
.operator().move_data().inits
[mpi_ever_init
];
140 s
.push_str(&format
!("{:?}", ever_init
));
144 fmt
::Display
::fmt(&s
, fmt
)