Auto merge of #60266 - albins:polonius-liveness, r=nikomatsakis

Fact generation for liveness calculations in Polonius

This PR tracks ongoing work to extend `rustc` with support for generating variable use, definition, and later also drop output for the Polonius solver, the whole of which is being tracked in [Polonius Issue #104](https://github.com/rust-lang/polonius/issues/104).
This commit is contained in:
bors 2019-07-13 10:15:40 +00:00
commit 6b468c6360
10 changed files with 448 additions and 627 deletions

View File

@ -2214,7 +2214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "polonius-engine"
version = "0.7.0"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2686,7 +2686,7 @@ dependencies = [
"measureme 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_apfloat 0.0.0",
@ -3203,7 +3203,7 @@ dependencies = [
"graphviz 0.0.0",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_apfloat 0.0.0",
"rustc_data_structures 0.0.0",
@ -4695,7 +4695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum polonius-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b24942fee141ea45628484a453762bb7e515099c3ec05fbeb76b7bf57b1aeed"
"checksum polonius-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
"checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"

View File

@ -19,9 +19,9 @@ lazy_static = "1.0.0"
num_cpus = "1.0"
scoped-tls = "1.0"
log = { version = "0.4", features = ["release_max_level_info", "std"] }
polonius-engine = "0.7.0"
rustc-rayon = "0.2.0"
rustc-rayon-core = "0.2.0"
polonius-engine = "0.9.0"
rustc_apfloat = { path = "../librustc_apfloat" }
rustc_target = { path = "../librustc_target" }
rustc_macros = { path = "../librustc_macros" }

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@ either = "1.5.0"
dot = { path = "../libgraphviz", package = "graphviz" }
log = "0.4"
log_settings = "0.1.1"
polonius-engine = "0.7.0"
polonius-engine = "0.9.0"
rustc = { path = "../librustc" }
rustc_target = { path = "../librustc_target" }
rustc_data_structures = { path = "../librustc_data_structures" }

View File

@ -3,7 +3,7 @@
//! 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 rustc::mir::{BasicBlock, Local, Location};
use rustc::ty::RegionVid;
use rustc_data_structures::bit_set::BitIter;
@ -15,12 +15,14 @@ use crate::dataflow::indexes::BorrowIndex;
use crate::dataflow::move_paths::HasMoveData;
use crate::dataflow::Borrows;
use crate::dataflow::EverInitializedPlaces;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation};
use crate::dataflow::MaybeUninitializedPlaces;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation};
use either::Either;
use std::fmt;
use std::rc::Rc;
crate type PoloniusOutput = Output<RegionVid, BorrowIndex, LocationIndex, Local>;
// (forced to be `pub` due to its use as an associated type below.)
crate struct Flows<'b, 'tcx> {
borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
@ -28,7 +30,7 @@ crate struct Flows<'b, 'tcx> {
pub ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'tcx>>,
/// Polonius Output
pub polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
pub polonius_output: Option<Rc<PoloniusOutput>>,
}
impl<'b, 'tcx> Flows<'b, 'tcx> {
@ -36,14 +38,9 @@ impl<'b, 'tcx> Flows<'b, 'tcx> {
borrows: FlowAtLocation<'tcx, Borrows<'b, 'tcx>>,
uninits: FlowAtLocation<'tcx, MaybeUninitializedPlaces<'b, 'tcx>>,
ever_inits: FlowAtLocation<'tcx, EverInitializedPlaces<'b, 'tcx>>,
polonius_output: Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
polonius_output: Option<Rc<PoloniusOutput>>,
) -> Self {
Flows {
borrows,
uninits,
ever_inits,
polonius_output,
}
Flows { borrows, uninits, ever_inits, polonius_output }
}
crate fn borrows_in_scope(

View File

@ -2,6 +2,7 @@ use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::dataflow::indexes::BorrowIndex;
use polonius_engine::AllFacts as PoloniusAllFacts;
use polonius_engine::Atom;
use rustc::mir::Local;
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
use std::error::Error;
@ -10,7 +11,7 @@ use std::fs::{self, File};
use std::io::Write;
use std::path::Path;
crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex>;
crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex, Local>;
crate trait AllFactsExt {
/// Returns `true` if there is a need to gather `AllFacts` given the
@ -27,8 +28,7 @@ crate trait AllFactsExt {
impl AllFactsExt for AllFacts {
/// Return
fn enabled(tcx: TyCtxt<'_>) -> bool {
tcx.sess.opts.debugging_opts.nll_facts
|| tcx.sess.opts.debugging_opts.polonius
tcx.sess.opts.debugging_opts.nll_facts || tcx.sess.opts.debugging_opts.polonius
}
fn write_to_dir(
@ -60,6 +60,12 @@ impl AllFactsExt for AllFacts {
outlives,
region_live_at,
invalidates,
var_used,
var_defined,
var_drop_used,
var_uses_region,
var_drops_region,
var_initialized_on_exit,
])
}
Ok(())
@ -84,11 +90,7 @@ struct FactWriter<'w> {
}
impl<'w> FactWriter<'w> {
fn write_facts_to_path<T>(
&self,
rows: &[T],
file_name: &str,
) -> Result<(), Box<dyn Error>>
fn write_facts_to_path<T>(&self, rows: &[T], file_name: &str) -> Result<(), Box<dyn Error>>
where
T: FactRow,
{
@ -102,19 +104,11 @@ impl<'w> FactWriter<'w> {
}
trait FactRow {
fn write(
&self,
out: &mut File,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>>;
fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>>;
}
impl FactRow for RegionVid {
fn write(
&self,
out: &mut File,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>> {
fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
write_row(out, location_table, &[self])
}
}
@ -124,11 +118,7 @@ where
A: FactCell,
B: FactCell,
{
fn write(
&self,
out: &mut File,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>> {
fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
write_row(out, location_table, &[&self.0, &self.1])
}
}
@ -139,11 +129,7 @@ where
B: FactCell,
C: FactCell,
{
fn write(
&self,
out: &mut File,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>> {
fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
write_row(out, location_table, &[&self.0, &self.1, &self.2])
}
}
@ -155,11 +141,7 @@ where
C: FactCell,
D: FactCell,
{
fn write(
&self,
out: &mut File,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>> {
fn write(&self, out: &mut File, location_table: &LocationTable) -> Result<(), Box<dyn Error>> {
write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
}
}
@ -170,11 +152,7 @@ fn write_row(
columns: &[&dyn FactCell],
) -> Result<(), Box<dyn Error>> {
for (index, c) in columns.iter().enumerate() {
let tail = if index == columns.len() - 1 {
"\n"
} else {
"\t"
};
let tail = if index == columns.len() - 1 { "\n" } else { "\t" };
write!(out, "{:?}{}", c.to_string(location_table), tail)?;
}
Ok(())

View File

@ -11,7 +11,7 @@ use crate::transform::MirSource;
use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Body};
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body};
use rustc::ty::{self, RegionKind, RegionVid};
use rustc_errors::Diagnostic;
use std::fmt::Debug;
@ -84,7 +84,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
errors_buffer: &mut Vec<Diagnostic>,
) -> (
RegionInferenceContext<'tcx>,
Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex, Local>>>,
Option<ClosureRegionRequirements<'tcx>>,
) {
let mut all_facts = if AllFacts::enabled(infcx.tcx) {

View File

@ -7,7 +7,7 @@ use crate::borrow_check::nll::ToRegionVid;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
use rustc::mir::{Local, Body};
use rustc::mir::{Body, Local};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use std::rc::Rc;
@ -15,6 +15,7 @@ use std::rc::Rc;
use super::TypeChecker;
mod local_use_map;
mod polonius;
mod trace;
/// Combines liveness analysis with initialization analysis to
@ -57,15 +58,9 @@ pub(super) fn generate<'tcx>(
};
if !live_locals.is_empty() {
trace::trace(
typeck,
body,
elements,
flow_inits,
move_data,
live_locals,
location_table,
);
trace::trace(typeck, body, elements, flow_inits, move_data, live_locals, location_table);
polonius::populate_var_liveness_facts(typeck, body, location_table);
}
}

View File

@ -0,0 +1,94 @@
use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::util::liveness::{categorize, DefUse};
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::{Body, Local, Location};
use rustc::ty::subst::Kind;
use rustc::ty::Ty;
use super::TypeChecker;
type VarPointRelations = Vec<(Local, LocationIndex)>;
struct LivenessPointFactsExtractor<'me> {
var_defined: &'me mut VarPointRelations,
var_used: &'me mut VarPointRelations,
location_table: &'me LocationTable,
}
// A Visitor to walk through the MIR and extract point-wise facts
impl LivenessPointFactsExtractor<'_> {
fn location_to_index(&self, location: Location) -> LocationIndex {
self.location_table.mid_index(location)
}
fn insert_def(&mut self, local: Local, location: Location) {
debug!("LivenessFactsExtractor::insert_def()");
self.var_defined.push((local, self.location_to_index(location)));
}
fn insert_use(&mut self, local: Local, location: Location) {
debug!("LivenessFactsExtractor::insert_use()");
self.var_used.push((local, self.location_to_index(location)));
}
}
impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> {
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
match categorize(context) {
Some(DefUse::Def) => self.insert_def(local, location),
Some(DefUse::Use) => self.insert_use(local, location),
_ => (),
// NOTE: Drop handling is now done in trace()
}
}
}
fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) {
debug!("add_regions(local={:?}, type={:?})", local, ty);
typeck.tcx().for_each_free_region(&ty, |region| {
let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(region);
debug!("add_regions for region {:?}", region_vid);
if let Some(facts) = typeck.borrowck_context.all_facts {
facts.var_uses_region.push((local, region_vid));
}
});
}
pub(super) fn populate_var_liveness_facts(
typeck: &mut TypeChecker<'_, 'tcx>,
mir: &Body<'tcx>,
location_table: &LocationTable,
) {
debug!("populate_var_liveness_facts()");
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
LivenessPointFactsExtractor {
var_defined: &mut facts.var_defined,
var_used: &mut facts.var_used,
location_table,
}
.visit_body(mir);
}
for (local, local_decl) in mir.local_decls.iter_enumerated() {
add_var_uses_regions(typeck, local, local_decl.ty);
}
}
// For every potentially drop()-touched region `region` in `local`'s type
// (`kind`), emit a Polonius `var_drops_region(local, region)` fact.
pub(super) fn add_var_drops_regions(
typeck: &mut TypeChecker<'_, 'tcx>,
local: Local,
kind: &Kind<'tcx>,
) {
debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
let tcx = typeck.tcx();
tcx.for_each_free_region(kind, |drop_live_region| {
let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(drop_live_region);
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
facts.var_drops_region.push((local, region_vid));
};
});
}

View File

@ -1,13 +1,14 @@
use crate::borrow_check::location::LocationTable;
use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
use crate::borrow_check::nll::type_check::liveness::polonius;
use crate::borrow_check::nll::type_check::NormalizeLocation;
use crate::borrow_check::nll::type_check::TypeChecker;
use crate::dataflow::indexes::MovePathIndex;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
use rustc::infer::canonical::QueryRegionConstraints;
use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Body};
use rustc::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc::traits::query::type_op::outlives::DropckOutlives;
use rustc::traits::query::type_op::TypeOp;
@ -130,6 +131,12 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
for local in live_locals {
self.reset_local_state();
self.add_defs_for(local);
// FIXME: this is temporary until we can generate our own initialization
if self.cx.typeck.borrowck_context.all_facts.is_some() {
self.add_polonius_var_initialized_on_exit_for(local)
}
self.compute_use_live_points_for(local);
self.compute_drop_live_points_for(local);
@ -150,6 +157,63 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}
}
// WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None
//
// FIXME: this analysis (the initialization tracking) should be
// done in Polonius, but isn't yet.
fn add_polonius_var_initialized_on_exit_for(&mut self, local: Local) {
let move_path = self.cx.move_data.rev_lookup.find_local(local);
let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap();
for block in self.cx.body.basic_blocks().indices() {
debug!("polonius: generating initialization facts for {:?} in {:?}", local, block);
// iterate through the block, applying the effects of each statement
// up to and including location, and populate `var_initialized_on_exit`
self.cx.flow_inits.reset_to_entry_of(block);
let start_location = Location { block, statement_index: 0 };
self.cx.flow_inits.apply_local_effect(start_location);
for statement_index in 0..self.cx.body[block].statements.len() {
let current_location = Location { block, statement_index };
self.cx.flow_inits.reconstruct_statement_effect(current_location);
// statement has not yet taken effect:
if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
facts
.var_initialized_on_exit
.push((local, self.cx.location_table.start_index(current_location)));
}
// statement has now taken effect
self.cx.flow_inits.apply_local_effect(current_location);
if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
facts
.var_initialized_on_exit
.push((local, self.cx.location_table.mid_index(current_location)));
}
}
let terminator_location = self.cx.body.terminator_loc(block);
if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
facts
.var_initialized_on_exit
.push((local, self.cx.location_table.start_index(terminator_location)));
}
// apply the effects of the terminator and push it if needed
self.cx.flow_inits.reset_to_exit_of(block);
if self.cx.flow_inits.has_any_child_of(move_path).is_some() {
facts
.var_initialized_on_exit
.push((local, self.cx.location_table.mid_index(terminator_location)));
}
}
}
/// Clear the value of fields that are "per local variable".
fn reset_local_state(&mut self) {
self.defs.clear();
@ -183,9 +247,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}
if self.use_live_at.insert(p) {
self.cx
.elements
.push_predecessors(self.cx.body, p, &mut self.stack)
self.cx.elements.push_predecessors(self.cx.body, p, &mut self.stack)
}
}
}
@ -211,6 +273,11 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
if self.cx.initialized_at_terminator(location.block, mpi) {
// FIXME: this analysis (the initialization tracking) should be
// done in Polonius, but isn't yet.
if let Some(facts) = self.cx.typeck.borrowck_context.all_facts {
facts.var_drop_used.push((local, self.cx.location_table.mid_index(location)));
}
if self.drop_live_at.insert(drop_point) {
self.drop_locations.push(location);
self.stack.push(drop_point);
@ -218,10 +285,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}
}
debug!(
"compute_drop_live_points_for: drop_locations={:?}",
self.drop_locations
);
debug!("compute_drop_live_points_for: drop_locations={:?}", self.drop_locations);
// Reverse DFS. But for drops, we do it a bit differently.
// The stack only ever stores *terminators of blocks*. Within
@ -257,17 +321,11 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
// block. One of them may be either a definition or use
// live point.
let term_location = self.cx.elements.to_location(term_point);
debug_assert_eq!(
self.cx.body.terminator_loc(term_location.block),
term_location,
);
debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,);
let block = term_location.block;
let entry_point = self.cx.elements.entry_point(term_location.block);
for p in (entry_point..term_point).rev() {
debug!(
"compute_drop_live_points_for_block: p = {:?}",
self.cx.elements.to_location(p),
);
debug!("compute_drop_live_points_for_block: p = {:?}", self.cx.elements.to_location(p));
if self.defs.contains(p) {
debug!("compute_drop_live_points_for_block: def site");
@ -286,10 +344,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}
for &pred_block in self.cx.body.predecessors_for(block).iter() {
debug!(
"compute_drop_live_points_for_block: pred_block = {:?}",
pred_block,
);
debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,);
// Check whether the variable is (at least partially)
// initialized at the exit of this predecessor. If so, we
@ -320,18 +375,12 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
// If the terminator of this predecessor either *assigns*
// our value or is a "normal use", then stop.
if self.defs.contains(pred_term_point) {
debug!(
"compute_drop_live_points_for_block: defined at {:?}",
pred_term_loc
);
debug!("compute_drop_live_points_for_block: defined at {:?}", pred_term_loc);
continue;
}
if self.use_live_at.contains(pred_term_point) {
debug!(
"compute_drop_live_points_for_block: use-live at {:?}",
pred_term_loc
);
debug!("compute_drop_live_points_for_block: use-live at {:?}", pred_term_loc);
continue;
}
@ -392,10 +441,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
// "just ahead" of a terminator.
self.flow_inits.reset_to_entry_of(block);
for statement_index in 0..self.body[block].statements.len() {
let location = Location {
block,
statement_index,
};
let location = Location { block, statement_index };
self.flow_inits.reconstruct_statement_effect(location);
self.flow_inits.apply_local_effect(location);
}
@ -462,12 +508,11 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
if let Some(data) = &drop_data.region_constraint_data {
for &drop_location in drop_locations {
self.typeck
.push_region_constraints(
drop_location.to_locations(),
ConstraintCategory::Boring,
data,
);
self.typeck.push_region_constraints(
drop_location.to_locations(),
ConstraintCategory::Boring,
data,
);
}
}
@ -487,6 +532,8 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
live_at,
self.location_table,
);
polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind);
}
}
@ -505,14 +552,15 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
let tcx = typeck.tcx();
tcx.for_each_free_region(&value, |live_region| {
let live_region_vid = typeck.borrowck_context
.universal_regions
.to_region_vid(live_region);
typeck.borrowck_context
let live_region_vid =
typeck.borrowck_context.universal_regions.to_region_vid(live_region);
typeck
.borrowck_context
.constraints
.liveness_constraints
.add_elements(live_region_vid, live_at);
// FIXME: remove this when we can generate our own region-live-at reliably
if let Some(facts) = typeck.borrowck_context.all_facts {
for point in live_at.iter() {
let loc = elements.to_location(point);
@ -530,14 +578,9 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
let param_env = typeck.param_env;
let (dropck_result, region_constraint_data) = param_env
.and(DropckOutlives::new(dropped_ty))
.fully_perform(typeck.infcx)
.unwrap();
let (dropck_result, region_constraint_data) =
param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap();
DropData {
dropck_result,
region_constraint_data,
}
DropData { dropck_result, region_constraint_data }
}
}