nll: remove NllLivenessMap and LiveVar
Extract the `compute` logic (now renamed `compute_live_locals`) from `NllLivenessMap` to the `liveness` module. Remove the unused structures.
This commit is contained in:
parent
4ae4e0501b
commit
d6ede9192d
4 changed files with 71 additions and 117 deletions
|
|
@ -2,7 +2,6 @@ use crate::borrow_check::borrow_set::BorrowSet;
|
|||
use crate::borrow_check::location::{LocationIndex, LocationTable};
|
||||
use crate::borrow_check::nll::facts::AllFactsExt;
|
||||
use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
|
||||
use crate::borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap;
|
||||
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
|
||||
use crate::dataflow::indexes::BorrowIndex;
|
||||
use crate::dataflow::move_paths::MoveData;
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
//! For the NLL computation, we need to compute liveness, but only for those
|
||||
//! local variables whose types contain regions. The others are not of interest
|
||||
//! to us. This file defines a new index type (LiveVar) that indexes into
|
||||
//! a list of "variables whose type contain regions". It also defines a map from
|
||||
//! Local to LiveVar and vice versa -- this map can be given to the
|
||||
//! liveness code so that it only operates over variables with regions in their
|
||||
//! types, instead of all variables.
|
||||
|
||||
use crate::borrow_check::nll::ToRegionVid;
|
||||
use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
|
||||
use crate::util::liveness::LiveVariableMap;
|
||||
use rustc::mir::{Local, Mir};
|
||||
use rustc::ty::{RegionVid, TyCtxt};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
|
||||
/// Map between Local and LiveVar indices: the purpose of this
|
||||
/// map is to define the subset of local variables for which we need
|
||||
/// to do a liveness computation. We only need to compute whether a
|
||||
/// variable `X` is live if that variable contains some region `R` in
|
||||
/// its type where `R` is not known to outlive a free region (i.e.,
|
||||
/// where `R` may be valid for just a subset of the fn body).
|
||||
crate struct NllLivenessMap {
|
||||
/// For each local variable, contains `Some(i)` if liveness is
|
||||
/// needed for this variable.
|
||||
pub from_local: IndexVec<Local, Option<LiveVar>>,
|
||||
|
||||
/// For each `LiveVar`, maps back to the original `Local` index.
|
||||
pub to_local: IndexVec<LiveVar, Local>,
|
||||
}
|
||||
|
||||
impl LiveVariableMap for NllLivenessMap {
|
||||
fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
|
||||
self.from_local[local]
|
||||
}
|
||||
|
||||
type LiveVar = LiveVar;
|
||||
|
||||
fn from_live_var(&self, local: Self::LiveVar) -> Local {
|
||||
self.to_local[local]
|
||||
}
|
||||
|
||||
fn num_variables(&self) -> usize {
|
||||
self.to_local.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl NllLivenessMap {
|
||||
crate fn compute(
|
||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||
free_regions: &FxHashSet<RegionVid>,
|
||||
mir: &Mir<'tcx>,
|
||||
) -> Self {
|
||||
let mut to_local = IndexVec::default();
|
||||
let facts_enabled = AllFacts::enabled(tcx);
|
||||
let from_local: IndexVec<Local, Option<_>> = mir.local_decls
|
||||
.iter_enumerated()
|
||||
.map(|(local, local_decl)| {
|
||||
if tcx.all_free_regions_meet(&local_decl.ty, |r| {
|
||||
free_regions.contains(&r.to_region_vid())
|
||||
}) && !facts_enabled {
|
||||
// If all the regions in the type are free regions
|
||||
// (or there are no regions), then we don't need
|
||||
// to track liveness for this variable.
|
||||
None
|
||||
} else {
|
||||
Some(to_local.push(local))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
debug!("{} total variables", mir.local_decls.len());
|
||||
debug!("{} variables need liveness", to_local.len());
|
||||
debug!("{} regions outlive free regions", free_regions.len());
|
||||
|
||||
Self {
|
||||
from_local,
|
||||
to_local,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if there are no local variables that need liveness computation.
|
||||
crate fn is_empty(&self) -> bool {
|
||||
self.to_local.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// Index given to each local variable for which we need to
|
||||
/// compute liveness information. For many locals, we are able to
|
||||
/// skip liveness information: for example, those variables whose
|
||||
/// types contain no regions.
|
||||
newtype_index! {
|
||||
pub struct LiveVar { .. }
|
||||
}
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
use crate::borrow_check::location::LocationTable;
|
||||
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
|
||||
use crate::borrow_check::nll::constraints::ConstraintSet;
|
||||
use crate::borrow_check::nll::NllLivenessMap;
|
||||
use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
|
||||
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
|
||||
use crate::borrow_check::nll::universal_regions::UniversalRegions;
|
||||
use crate::borrow_check::nll::ToRegionVid;
|
||||
use crate::dataflow::move_paths::MoveData;
|
||||
use crate::dataflow::MaybeInitializedPlaces;
|
||||
use crate::dataflow::FlowAtLocation;
|
||||
use rustc::mir::Mir;
|
||||
use rustc::ty::RegionVid;
|
||||
use crate::dataflow::MaybeInitializedPlaces;
|
||||
use rustc::mir::{Local, Mir};
|
||||
use rustc::ty::{RegionVid, TyCtxt};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::TypeChecker;
|
||||
|
||||
crate mod liveness_map;
|
||||
mod local_use_map;
|
||||
mod trace;
|
||||
|
||||
|
|
@ -34,16 +34,71 @@ pub(super) fn generate<'gcx, 'tcx>(
|
|||
location_table: &LocationTable,
|
||||
) {
|
||||
debug!("liveness::generate");
|
||||
let free_regions = {
|
||||
let borrowck_context = typeck.borrowck_context.as_ref().unwrap();
|
||||
regions_that_outlive_free_regions(
|
||||
typeck.infcx.num_region_vars(),
|
||||
&borrowck_context.universal_regions,
|
||||
&borrowck_context.constraints.outlives_constraints,
|
||||
)
|
||||
|
||||
let live_locals: Vec<Local> = if AllFacts::enabled(typeck.tcx()) {
|
||||
// If "dump facts from NLL analysis" was requested perform
|
||||
// the liveness analysis for all `Local`s. This case opens
|
||||
// the possibility of the variables being analyzed in `trace`
|
||||
// to be *any* `Local`, not just the "live" ones, so we can't
|
||||
// make any assumptions past this point as to the characteristics
|
||||
// of the `live_locals`.
|
||||
// FIXME: Review "live" terminology past this point, we should
|
||||
// not be naming the `Local`s as live.
|
||||
mir.local_decls.indices().collect()
|
||||
} else {
|
||||
let free_regions = {
|
||||
let borrowck_context = typeck.borrowck_context.as_ref().unwrap();
|
||||
regions_that_outlive_free_regions(
|
||||
typeck.infcx.num_region_vars(),
|
||||
&borrowck_context.universal_regions,
|
||||
&borrowck_context.constraints.outlives_constraints,
|
||||
)
|
||||
};
|
||||
compute_live_locals(typeck.tcx(), &free_regions, mir)
|
||||
};
|
||||
let liveness_map = NllLivenessMap::compute(typeck.tcx(), &free_regions, mir);
|
||||
trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map, location_table);
|
||||
|
||||
if !live_locals.is_empty() {
|
||||
trace::trace(
|
||||
typeck,
|
||||
mir,
|
||||
elements,
|
||||
flow_inits,
|
||||
move_data,
|
||||
live_locals,
|
||||
location_table,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The purpose of `compute_live_locals` is to define the subset of `Local`
|
||||
// variables for which we need to do a liveness computation. We only need
|
||||
// to compute whether a variable `X` is live if that variable contains
|
||||
// some region `R` in its type where `R` is not known to outlive a free
|
||||
// region (i.e., where `R` may be valid for just a subset of the fn body).
|
||||
fn compute_live_locals(
|
||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||
free_regions: &FxHashSet<RegionVid>,
|
||||
mir: &Mir<'tcx>,
|
||||
) -> Vec<Local> {
|
||||
let live_locals: Vec<Local> = mir
|
||||
.local_decls
|
||||
.iter_enumerated()
|
||||
.filter_map(|(local, local_decl)| {
|
||||
if tcx.all_free_regions_meet(&local_decl.ty, |r| {
|
||||
free_regions.contains(&r.to_region_vid())
|
||||
}) {
|
||||
None
|
||||
} else {
|
||||
Some(local)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
debug!("{} total variables", mir.local_decls.len());
|
||||
debug!("{} variables need liveness", live_locals.len());
|
||||
debug!("{} regions outlive free regions", free_regions.len());
|
||||
|
||||
live_locals
|
||||
}
|
||||
|
||||
/// Computes all regions that are (currently) known to outlive free
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
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::liveness_map::NllLivenessMap;
|
||||
use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
|
||||
use crate::borrow_check::nll::type_check::NormalizeLocation;
|
||||
use crate::borrow_check::nll::type_check::TypeChecker;
|
||||
|
|
@ -37,16 +36,11 @@ pub(super) fn trace(
|
|||
elements: &Rc<RegionValueElements>,
|
||||
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
liveness_map: &NllLivenessMap,
|
||||
live_locals: Vec<Local>,
|
||||
location_table: &LocationTable,
|
||||
) {
|
||||
debug!("trace()");
|
||||
|
||||
if liveness_map.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let live_locals: Vec<Local> = liveness_map.to_local.clone().into_iter().collect();
|
||||
let local_use_map = &LocalUseMap::build(&live_locals, elements, mir);
|
||||
|
||||
let cx = LivenessContext {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue