162 lines
5.5 KiB
Rust
162 lines
5.5 KiB
Rust
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
//! Manages the dataflow bits required for borrowck.
|
|
//!
|
|
//! FIXME: this might be better as a "generic" fixed-point combinator,
|
|
//! but is not as ugly as it is right now.
|
|
|
|
use rustc::mir::{BasicBlock, Location};
|
|
|
|
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
|
|
use dataflow::{EverInitializedPlaces, MovingOutStatements};
|
|
use dataflow::{Borrows};
|
|
use dataflow::{FlowAtLocation, FlowsAtLocation};
|
|
use dataflow::move_paths::HasMoveData;
|
|
use std::fmt;
|
|
|
|
// (forced to be `pub` due to its use as an associated type below.)
|
|
pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> {
|
|
pub borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
|
|
pub inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
|
|
pub uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
|
|
pub move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
|
|
pub ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
|
|
}
|
|
|
|
impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> {
|
|
pub fn new(
|
|
borrows: FlowAtLocation<Borrows<'b, 'gcx, 'tcx>>,
|
|
inits: FlowAtLocation<MaybeInitializedPlaces<'b, 'gcx, 'tcx>>,
|
|
uninits: FlowAtLocation<MaybeUninitializedPlaces<'b, 'gcx, 'tcx>>,
|
|
move_outs: FlowAtLocation<MovingOutStatements<'b, 'gcx, 'tcx>>,
|
|
ever_inits: FlowAtLocation<EverInitializedPlaces<'b, 'gcx, 'tcx>>,
|
|
) -> Self {
|
|
Flows {
|
|
borrows,
|
|
inits,
|
|
uninits,
|
|
move_outs,
|
|
ever_inits,
|
|
}
|
|
}
|
|
}
|
|
|
|
macro_rules! each_flow {
|
|
($this:ident, $meth:ident($arg:ident)) => {
|
|
FlowAtLocation::$meth(&mut $this.borrows, $arg);
|
|
FlowAtLocation::$meth(&mut $this.inits, $arg);
|
|
FlowAtLocation::$meth(&mut $this.uninits, $arg);
|
|
FlowAtLocation::$meth(&mut $this.move_outs, $arg);
|
|
FlowAtLocation::$meth(&mut $this.ever_inits, $arg);
|
|
}
|
|
}
|
|
|
|
impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
|
|
fn reset_to_entry_of(&mut self, bb: BasicBlock) {
|
|
each_flow!(self, reset_to_entry_of(bb));
|
|
}
|
|
|
|
fn reconstruct_statement_effect(&mut self, location: Location) {
|
|
each_flow!(self, reconstruct_statement_effect(location));
|
|
}
|
|
|
|
fn reconstruct_terminator_effect(&mut self, location: Location) {
|
|
each_flow!(self, reconstruct_terminator_effect(location));
|
|
}
|
|
|
|
fn apply_local_effect(&mut self, location: Location) {
|
|
each_flow!(self, apply_local_effect(location));
|
|
}
|
|
}
|
|
|
|
impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> {
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
let mut s = String::new();
|
|
|
|
s.push_str("borrows in effect: [");
|
|
let mut saw_one = false;
|
|
self.borrows.each_state_bit(|borrow| {
|
|
if saw_one {
|
|
s.push_str(", ");
|
|
};
|
|
saw_one = true;
|
|
let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
|
|
s.push_str(&format!("{}{}", borrow_data,
|
|
if borrow.is_activation() { "@active" } else { "" }));
|
|
});
|
|
s.push_str("] ");
|
|
|
|
s.push_str("borrows generated: [");
|
|
let mut saw_one = false;
|
|
self.borrows.each_gen_bit(|borrow| {
|
|
if saw_one {
|
|
s.push_str(", ");
|
|
};
|
|
saw_one = true;
|
|
let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()];
|
|
s.push_str(&format!("{}", borrow_data));
|
|
});
|
|
s.push_str("] ");
|
|
|
|
s.push_str("inits: [");
|
|
let mut saw_one = false;
|
|
self.inits.each_state_bit(|mpi_init| {
|
|
if saw_one {
|
|
s.push_str(", ");
|
|
};
|
|
saw_one = true;
|
|
let move_path = &self.inits.operator().move_data().move_paths[mpi_init];
|
|
s.push_str(&format!("{}", move_path));
|
|
});
|
|
s.push_str("] ");
|
|
|
|
s.push_str("uninits: [");
|
|
let mut saw_one = false;
|
|
self.uninits.each_state_bit(|mpi_uninit| {
|
|
if saw_one {
|
|
s.push_str(", ");
|
|
};
|
|
saw_one = true;
|
|
let move_path =
|
|
&self.uninits.operator().move_data().move_paths[mpi_uninit];
|
|
s.push_str(&format!("{}", move_path));
|
|
});
|
|
s.push_str("] ");
|
|
|
|
s.push_str("move_out: [");
|
|
let mut saw_one = false;
|
|
self.move_outs.each_state_bit(|mpi_move_out| {
|
|
if saw_one {
|
|
s.push_str(", ");
|
|
};
|
|
saw_one = true;
|
|
let move_out = &self.move_outs.operator().move_data().moves[mpi_move_out];
|
|
s.push_str(&format!("{:?}", move_out));
|
|
});
|
|
s.push_str("] ");
|
|
|
|
s.push_str("ever_init: [");
|
|
let mut saw_one = false;
|
|
self.ever_inits.each_state_bit(|mpi_ever_init| {
|
|
if saw_one {
|
|
s.push_str(", ");
|
|
};
|
|
saw_one = true;
|
|
let ever_init =
|
|
&self.ever_inits.operator().move_data().inits[mpi_ever_init];
|
|
s.push_str(&format!("{:?}", ever_init));
|
|
});
|
|
s.push_str("]");
|
|
|
|
fmt::Display::fmt(&s, fmt)
|
|
}
|
|
}
|