]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/liveness_map.rs
Account for --remap-path-prefix in save-analysis
[rust.git] / src / librustc_mir / borrow_check / nll / liveness_map.rs
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.
4 //
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.
10
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.
18
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;
24
25 use rustc_data_structures::indexed_vec::Idx;
26
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
29 /// contain regions.
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>>,
34
35     /// For each LocalWithRegion, maps back to the original Local index.
36     to_local: IndexVec<LocalWithRegion, Local>,
37 }
38
39 impl LiveVariableMap for NllLivenessMap {
40     fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
41         self.from_local[local]
42     }
43
44     type LiveVar = LocalWithRegion;
45
46     fn from_live_var(&self, local: Self::LiveVar) -> Local {
47         self.to_local[local]
48     }
49
50     fn num_variables(&self) -> usize {
51         self.to_local.len()
52     }
53 }
54
55 impl NllLivenessMap {
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);
60
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
65             .local_decls
66             .iter_enumerated()
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
74                     // statics.
75                     escapes_into_return += 1;
76                     None
77                 } else if local_decl.ty.has_free_regions() {
78                     let l = to_local.push(local);
79                     debug!("liveness_map: {:?} = {:?}", local, l);
80                     Some(l)
81                 } else {
82                     no_regions += 1;
83                     None
84                 }
85             }).collect();
86
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);
90
91         Self {
92             from_local,
93             to_local,
94         }
95     }
96 }
97
98 /// Index given to each local variable whose type contains a region.
99 newtype_index!(LocalWithRegion);