1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! For the NLL computation, we need to compute liveness, but only for those
12 //! local variables whose types contain regions. The others are not of interest
13 //! to us. This file defines a new index type (LocalWithRegion) that indexes into
14 //! a list of "variables whose type contain regions". It also defines a map from
15 //! Local to LocalWithRegion and vice versa -- this map can be given to the
16 //! liveness code so that it only operates over variables with regions in their
17 //! types, instead of all variables.
19 use borrow_check::nll::escaping_locals::EscapingLocals;
20 use rustc::mir::{Local, Mir};
21 use rustc::ty::TypeFoldable;
22 use rustc_data_structures::indexed_vec::IndexVec;
23 use util::liveness::LiveVariableMap;
25 use rustc_data_structures::indexed_vec::Idx;
27 /// Map between Local and LocalWithRegion indices: this map is supplied to the
28 /// liveness code so that it will only analyze those variables whose types
30 crate struct NllLivenessMap {
31 /// For each local variable, contains either None (if the type has no regions)
32 /// or Some(i) with a suitable index.
33 from_local: IndexVec<Local, Option<LocalWithRegion>>,
35 /// For each LocalWithRegion, maps back to the original Local index.
36 to_local: IndexVec<LocalWithRegion, Local>,
39 impl LiveVariableMap for NllLivenessMap {
40 fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
41 self.from_local[local]
44 type LiveVar = LocalWithRegion;
46 fn from_live_var(&self, local: Self::LiveVar) -> Local {
50 fn num_variables(&self) -> usize {
56 /// Iterates over the variables in Mir and assigns each Local whose type contains
57 /// regions a LocalWithRegion index. Returns a map for converting back and forth.
58 crate fn compute(mir: &Mir<'tcx>) -> Self {
59 let mut escaping_locals = EscapingLocals::compute(mir);
61 let mut to_local = IndexVec::default();
62 let mut escapes_into_return = 0;
63 let mut no_regions = 0;
64 let from_local: IndexVec<Local, Option<_>> = mir
67 .map(|(local, local_decl)| {
68 if escaping_locals.escapes_into_return(local) {
69 // If the local escapes into the return value,
70 // then the return value will force all of the
71 // regions in its type to outlive free regions
72 // (e.g., `'static`) and hence liveness is not
73 // needed. This is particularly important for big
75 escapes_into_return += 1;
77 } else if local_decl.ty.has_free_regions() {
78 let l = to_local.push(local);
79 debug!("liveness_map: {:?} = {:?}", local, l);
87 debug!("liveness_map: {} variables need liveness", to_local.len());
88 debug!("liveness_map: {} escapes into return", escapes_into_return);
89 debug!("liveness_map: {} no regions", no_regions);
98 /// Index given to each local variable whose type contains a region.
99 newtype_index!(LocalWithRegion);