mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
merge NLL "constraint generation" into liveness
This commit is contained in:
parent
626289a9e3
commit
96042bc247
@ -1,74 +0,0 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use rustc_middle::mir::visit::{TyContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Location, SourceInfo};
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{GenericArgsRef, Region, Ty, TyCtxt};
|
||||
|
||||
use crate::region_infer::values::LivenessValues;
|
||||
|
||||
pub(super) fn generate_constraints<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
liveness_constraints: &mut LivenessValues,
|
||||
body: &Body<'tcx>,
|
||||
) {
|
||||
let mut cg = ConstraintGeneration { tcx, liveness_constraints };
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
cg.visit_basic_block_data(bb, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// 'cg = the duration of the constraint generation process itself.
|
||||
struct ConstraintGeneration<'cg, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
liveness_constraints: &'cg mut LivenessValues,
|
||||
}
|
||||
|
||||
impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
|
||||
/// We sometimes have `args` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) {
|
||||
self.record_regions_live_at(*args, location);
|
||||
self.super_args(args);
|
||||
}
|
||||
|
||||
/// We sometimes have `region`s within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_region(&mut self, region: Region<'tcx>, location: Location) {
|
||||
self.record_regions_live_at(region, location);
|
||||
self.super_region(region);
|
||||
}
|
||||
|
||||
/// We sometimes have `ty`s within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
|
||||
match ty_context {
|
||||
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||
| TyContext::UserTy(span)
|
||||
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
||||
}
|
||||
TyContext::Location(location) => {
|
||||
self.record_regions_live_at(ty, location);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_ty(ty);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
|
||||
/// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
|
||||
/// all regions appearing in the type of `value` must be live at `location`.
|
||||
fn record_regions_live_at<T>(&mut self, value: T, location: Location)
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!("add_regular_live_constraint(value={:?}, location={:?})", value, location);
|
||||
self.tcx.for_each_free_region(&value, |live_region| {
|
||||
let live_region_vid = live_region.as_var();
|
||||
self.liveness_constraints.add_location(live_region_vid, location);
|
||||
});
|
||||
}
|
||||
}
|
@ -64,7 +64,6 @@ use self::path_utils::*;
|
||||
|
||||
pub mod borrow_set;
|
||||
mod borrowck_errors;
|
||||
mod constraint_generation;
|
||||
mod constraints;
|
||||
mod dataflow;
|
||||
mod def_use;
|
||||
|
@ -22,7 +22,6 @@ use std::str::FromStr;
|
||||
|
||||
use crate::{
|
||||
borrow_set::BorrowSet,
|
||||
constraint_generation,
|
||||
consumers::ConsumerOptions,
|
||||
diagnostics::RegionErrors,
|
||||
facts::{AllFacts, AllFactsExt, RustcFacts},
|
||||
@ -141,7 +140,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
let MirTypeckRegionConstraints {
|
||||
placeholder_indices,
|
||||
placeholder_index_to_region: _,
|
||||
mut liveness_constraints,
|
||||
liveness_constraints,
|
||||
outlives_constraints,
|
||||
member_constraints,
|
||||
universe_causes,
|
||||
@ -149,7 +148,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
} = constraints;
|
||||
let placeholder_indices = Rc::new(placeholder_indices);
|
||||
|
||||
constraint_generation::generate_constraints(infcx.tcx, &mut liveness_constraints, body);
|
||||
polonius::emit_cfg_and_loan_kills_facts(
|
||||
infcx.tcx,
|
||||
&mut all_facts,
|
||||
|
@ -1,7 +1,9 @@
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_middle::mir::visit::{TyContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location, SourceInfo};
|
||||
use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
@ -11,7 +13,7 @@ use crate::{
|
||||
constraints::OutlivesConstraintSet,
|
||||
facts::{AllFacts, AllFactsExt},
|
||||
location::LocationTable,
|
||||
region_infer::values::RegionValueElements,
|
||||
region_infer::values::{LivenessValues, RegionValueElements},
|
||||
universal_regions::UniversalRegions,
|
||||
};
|
||||
|
||||
@ -65,6 +67,14 @@ pub(super) fn generate<'mir, 'tcx>(
|
||||
boring_locals,
|
||||
polonius_drop_used,
|
||||
);
|
||||
|
||||
// Mark regions that should be live where they appear within rvalues or within a call: like
|
||||
// args, regions, and types.
|
||||
record_regular_live_regions(
|
||||
typeck.tcx(),
|
||||
&mut typeck.borrowck_context.constraints.liveness_constraints,
|
||||
body,
|
||||
);
|
||||
}
|
||||
|
||||
// The purpose of `compute_relevant_live_locals` is to define the subset of `Local`
|
||||
@ -132,3 +142,71 @@ fn regions_that_outlive_free_regions<'tcx>(
|
||||
// Return the final set of things we visited.
|
||||
outlives_free_region
|
||||
}
|
||||
|
||||
/// Some variables are "regular live" at `location` -- i.e., they may be used later. This means that
|
||||
/// all regions appearing in their type must be live at `location`.
|
||||
fn record_regular_live_regions<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
liveness_constraints: &mut LivenessValues,
|
||||
body: &Body<'tcx>,
|
||||
) {
|
||||
let mut visitor = LiveVariablesVisitor { tcx, liveness_constraints };
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
visitor.visit_basic_block_data(bb, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Visitor looking for regions that should be live within rvalues or calls.
|
||||
struct LiveVariablesVisitor<'cx, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
liveness_constraints: &'cx mut LivenessValues,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> {
|
||||
/// We sometimes have `args` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) {
|
||||
self.record_regions_live_at(*args, location);
|
||||
self.super_args(args);
|
||||
}
|
||||
|
||||
/// We sometimes have `region`s within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_region(&mut self, region: Region<'tcx>, location: Location) {
|
||||
self.record_regions_live_at(region, location);
|
||||
self.super_region(region);
|
||||
}
|
||||
|
||||
/// We sometimes have `ty`s within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
|
||||
match ty_context {
|
||||
TyContext::ReturnTy(SourceInfo { span, .. })
|
||||
| TyContext::YieldTy(SourceInfo { span, .. })
|
||||
| TyContext::UserTy(span)
|
||||
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
|
||||
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
|
||||
}
|
||||
TyContext::Location(location) => {
|
||||
self.record_regions_live_at(ty, location);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_ty(ty);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> LiveVariablesVisitor<'cx, 'tcx> {
|
||||
/// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
|
||||
/// all regions appearing in the type of `value` must be live at `location`.
|
||||
fn record_regions_live_at<T>(&mut self, value: T, location: Location)
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
debug!("record_regions_live_at(value={:?}, location={:?})", value, location);
|
||||
self.tcx.for_each_free_region(&value, |live_region| {
|
||||
let live_region_vid = live_region.as_var();
|
||||
self.liveness_constraints.add_location(live_region_vid, location);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user