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:
Lucas Molas 2019-02-15 01:04:16 -03:00
parent 4ae4e0501b
commit d6ede9192d
4 changed files with 71 additions and 117 deletions

View file

@ -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;

View file

@ -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 { .. }
}

View file

@ -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

View file

@ -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 {