use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::dataflow::indexes::BorrowIndex;
-use crate::dataflow::move_paths::{MoveData, MovePathIndex};
+use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind};
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
use crate::transform::MirSource;
use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
-use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted};
+use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted};
use rustc::ty::{self, RegionKind, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::Diagnostic;
universal_regions
}
+
+// This function populates an AllFacts instance with base facts related to
+// MovePaths and needed for the move analysis.
+fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) {
+ all_facts.var_starts_path.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (v, m)));
+
+ for (idx, move_path) in move_data.move_paths.iter_enumerated() {
+ all_facts.parent.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (parent, idx)));
+ }
+
+ // initialized_at
+ for init in move_data.inits.iter() {
+
+ match init.location {
+ InitLocation::Statement(location) => {
+ let block_data = &body[location.block];
+ let is_terminator = location.statement_index == block_data.statements.len();
+
+ if is_terminator && init.kind == InitKind::NonPanicPathOnly {
+ // We are at the terminator of an init that has a panic path,
+ // and where the init should not happen on panic
+
+ for &successor in block_data.terminator().successors() {
+ if body[successor].is_cleanup {
+ continue;
+ }
+
+ // The initialization happened in (or rather, when arriving at)
+ // the successors, but not in the unwind block.
+ let first_statement = Location { block: successor, statement_index: 0};
+ all_facts.initialized_at.push((init.path, location_table.start_index(first_statement)));
+ }
+
+ } else {
+ // In all other cases, the initialization just happens at the
+ // midpoint, like any other effect.
+ all_facts.initialized_at.push((init.path, location_table.mid_index(location)));
+ }
+ },
+ // Arguments are initialized on function entry
+ InitLocation::Argument(local) => {
+ assert!(body.local_kind(local) == LocalKind::Arg);
+ let fn_entry = Location {block: BasicBlock::from_u32(0u32), statement_index: 0 };
+ all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry)));
+
+ }
+ }
+ }
+
+
+ // moved_out_at
+ // deinitialisation is assumed to always happen!
+ all_facts.moved_out_at.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
+}
+
/// Computes the (non-lexical) regions from the input MIR.
///
/// This may result in errors being reported.
all_facts
.universal_region
.extend(universal_regions.universal_regions());
+ populate_polonius_move_facts(all_facts, move_data, location_table, body);
}
// Create the region inference context, taking ownership of the
var_defined: &'me mut VarPointRelations,
var_used: &'me mut VarPointRelations,
location_table: &'me LocationTable,
+ var_drop_used: &'me mut VarPointRelations,
}
// A Visitor to walk through the MIR and extract point-wise facts
debug!("LivenessFactsExtractor::insert_use()");
self.var_used.push((local, self.location_to_index(location)));
}
+
+ fn insert_drop_use(&mut self, local: Local, location: Location) {
+ debug!("LivenessFactsExtractor::insert_drop_use()");
+ self.var_drop_used.push((local, self.location_to_index(location)));
+ }
}
impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> {
match categorize(context) {
Some(DefUse::Def) => self.insert_def(local, location),
Some(DefUse::Use) => self.insert_use(local, location),
+ Some(DefUse::Drop) => self.insert_drop_use(local, location),
_ => (),
- // NOTE: Drop handling is now done in trace()
}
}
}
LivenessPointFactsExtractor {
var_defined: &mut facts.var_defined,
var_used: &mut facts.var_used,
+ var_drop_used: &mut facts.var_drop_used,
location_table,
}
.visit_body(mir);