1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! 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 borrow_check::nll::ToRegionVid; use rustc::mir::{Local, Mir}; use rustc::ty::{RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use util::liveness::LiveVariableMap; /// 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 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()) }) { // 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, } } /// 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 { .. } }