Skip to content

Commit 6b09477

Browse files
author
Albin Stjerna
committed
Polonius: emit initialization/move tracking facts
- var_starts_path - parent - initialized_at - moved_out_at This also switches to the intended emission of `var_drop_used` fact emission, where that fact is always emitted on a drop-use of a variable, regardless of its initialization status, as Polonius now handles that.
1 parent 996ba93 commit 6b09477

File tree

4 files changed

+74
-9
lines changed

4 files changed

+74
-9
lines changed

src/librustc_mir/borrow_check/nll/mod.rs

+58-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use crate::borrow_check::nll::facts::AllFactsExt;
44
use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
55
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
66
use crate::dataflow::indexes::BorrowIndex;
7-
use crate::dataflow::move_paths::{MoveData, MovePathIndex};
7+
use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind};
88
use crate::dataflow::FlowAtLocation;
99
use crate::dataflow::MaybeInitializedPlaces;
1010
use crate::transform::MirSource;
1111
use crate::borrow_check::Upvar;
1212
use rustc::hir::def_id::DefId;
1313
use rustc::infer::InferCtxt;
14-
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted};
14+
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted};
1515
use rustc::ty::{self, RegionKind, RegionVid};
1616
use rustc_data_structures::indexed_vec::IndexVec;
1717
use rustc_errors::Diagnostic;
@@ -69,6 +69,61 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
6969
universal_regions
7070
}
7171

72+
73+
// This function populates an AllFacts instance with base facts related to
74+
// MovePaths and needed for the move analysis.
75+
fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) {
76+
all_facts.var_starts_path.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (v, m)));
77+
78+
for (idx, move_path) in move_data.move_paths.iter_enumerated() {
79+
all_facts.parent.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (parent, idx)));
80+
}
81+
82+
// initialized_at
83+
for init in move_data.inits.iter() {
84+
85+
match init.location {
86+
InitLocation::Statement(location) => {
87+
let block_data = &body[location.block];
88+
let is_terminator = location.statement_index == block_data.statements.len();
89+
90+
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
91+
// We are at the terminator of an init that has a panic path,
92+
// and where the init should not happen on panic
93+
94+
for &successor in block_data.terminator().successors() {
95+
if body[successor].is_cleanup {
96+
continue;
97+
}
98+
99+
// The initialization happened in (or rather, when arriving at)
100+
// the successors, but not in the unwind block.
101+
let first_statement = Location { block: successor, statement_index: 0};
102+
all_facts.initialized_at.push((init.path, location_table.start_index(first_statement)));
103+
}
104+
105+
} else {
106+
// In all other cases, the initialization just happens at the
107+
// midpoint, like any other effect.
108+
all_facts.initialized_at.push((init.path, location_table.mid_index(location)));
109+
}
110+
},
111+
// Arguments are initialized on function entry
112+
InitLocation::Argument(local) => {
113+
assert!(body.local_kind(local) == LocalKind::Arg);
114+
let fn_entry = Location {block: BasicBlock::from_u32(0u32), statement_index: 0 };
115+
all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry)));
116+
117+
}
118+
}
119+
}
120+
121+
122+
// moved_out_at
123+
// deinitialisation is assumed to always happen!
124+
all_facts.moved_out_at.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
125+
}
126+
72127
/// Computes the (non-lexical) regions from the input MIR.
73128
///
74129
/// This may result in errors being reported.
@@ -123,6 +178,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
123178
all_facts
124179
.universal_region
125180
.extend(universal_regions.universal_regions());
181+
populate_polonius_move_facts(all_facts, move_data, location_table, body);
126182
}
127183

128184
// Create the region inference context, taking ownership of the

src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct LivenessPointFactsExtractor<'me> {
1313
var_defined: &'me mut VarPointRelations,
1414
var_used: &'me mut VarPointRelations,
1515
location_table: &'me LocationTable,
16+
var_drop_used: &'me mut VarPointRelations,
1617
}
1718

1819
// A Visitor to walk through the MIR and extract point-wise facts
@@ -30,15 +31,20 @@ impl LivenessPointFactsExtractor<'_> {
3031
debug!("LivenessFactsExtractor::insert_use()");
3132
self.var_used.push((local, self.location_to_index(location)));
3233
}
34+
35+
fn insert_drop_use(&mut self, local: Local, location: Location) {
36+
debug!("LivenessFactsExtractor::insert_drop_use()");
37+
self.var_drop_used.push((local, self.location_to_index(location)));
38+
}
3339
}
3440

3541
impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> {
3642
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
3743
match categorize(context) {
3844
Some(DefUse::Def) => self.insert_def(local, location),
3945
Some(DefUse::Use) => self.insert_use(local, location),
46+
Some(DefUse::Drop) => self.insert_drop_use(local, location),
4047
_ => (),
41-
// NOTE: Drop handling is now done in trace()
4248
}
4349
}
4450
}
@@ -65,6 +71,7 @@ pub(super) fn populate_var_liveness_facts(
6571
LivenessPointFactsExtractor {
6672
var_defined: &mut facts.var_defined,
6773
var_used: &mut facts.var_used,
74+
var_drop_used: &mut facts.var_drop_used,
6875
location_table,
6976
}
7077
.visit_body(mir);

src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs

-5
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
273273
debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
274274

275275
if self.cx.initialized_at_terminator(location.block, mpi) {
276-
// FIXME: this analysis (the initialization tracking) should be
277-
// done in Polonius, but isn't yet.
278-
if let Some(facts) = self.cx.typeck.borrowck_context.all_facts {
279-
facts.var_drop_used.push((local, self.cx.location_table.mid_index(location)));
280-
}
281276
if self.drop_live_at.insert(drop_point) {
282277
self.drop_locations.push(location);
283278
self.stack.push(drop_point);

src/librustc_mir/dataflow/move_paths/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use rustc::ty::{Ty, TyCtxt};
22
use rustc::mir::*;
33
use rustc::util::nodemap::FxHashMap;
4-
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
4+
use rustc_data_structures::indexed_vec::{Idx, IndexVec, Enumerated};
55
use smallvec::SmallVec;
66
use syntax_pos::{Span};
7+
use core::slice::Iter;
78

89
use std::fmt;
910
use std::ops::{Index, IndexMut};
@@ -262,6 +263,12 @@ impl MovePathLookup {
262263
pub fn find_local(&self, local: Local) -> MovePathIndex {
263264
self.locals[local]
264265
}
266+
267+
/// An enumerated iterator of `local`s and their associated
268+
/// `MovePathIndex`es.
269+
pub fn iter_locals_enumerated(&self) -> Enumerated<Local, Iter<'_, MovePathIndex>> {
270+
self.locals.iter_enumerated()
271+
}
265272
}
266273

267274
#[derive(Debug)]

0 commit comments

Comments
 (0)