diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 84fdbb9423e0a..2d3800dd1dda8 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -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; diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs deleted file mode 100644 index b9f9d83161b79..0000000000000 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs +++ /dev/null @@ -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>, - - /// For each `LiveVar`, maps back to the original `Local` index. - pub to_local: IndexVec, -} - -impl LiveVariableMap for NllLivenessMap { - fn from_local(&self, local: Local) -> Option { - 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, - mir: &Mir<'tcx>, - ) -> Self { - let mut to_local = IndexVec::default(); - let facts_enabled = AllFacts::enabled(tcx); - let from_local: IndexVec> = 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 { .. } -} diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 28a8cad8ca200..960e75048fa16 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -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 = 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, + mir: &Mir<'tcx>, +) -> Vec { + let live_locals: Vec = 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 diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 4950d0045d3ff..f0df7070e6b5a 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -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, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>, move_data: &MoveData<'tcx>, - liveness_map: &NllLivenessMap, + live_locals: Vec, location_table: &LocationTable, ) { debug!("trace()"); - if liveness_map.is_empty() { - return; - } - - let live_locals: Vec = liveness_map.to_local.clone().into_iter().collect(); let local_use_map = &LocalUseMap::build(&live_locals, elements, mir); let cx = LivenessContext {