]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs
Rollup merge of #53756 - dmerejkowsky:fix-comment, r=KodrAus
[rust.git] / src / librustc_mir / borrow_check / nll / type_check / liveness / local_use_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 use borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
12 use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
13 use rustc::mir::visit::{PlaceContext, Visitor};
14 use rustc::mir::{Local, Location, Mir};
15 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
16 use rustc_data_structures::vec_linked_list as vll;
17 use util::liveness::{categorize, DefUse, LiveVariableMap};
18
19 /// A map that cross references each local with the locations where it
20 /// is defined (assigned), used, or dropped. Used during liveness
21 /// computation.
22 crate struct LocalUseMap<'me> {
23     liveness_map: &'me NllLivenessMap,
24
25     /// Head of a linked list of **definitions** of each variable --
26     /// definition in this context means assignment, e.g. `x` is
27     /// defined in `x = y` but not `y`; that first def is the head of
28     /// a linked list that lets you enumerate all places the variable
29     /// is assigned.
30     first_def_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
31
32     /// Head of a linked list of **uses** of each variable -- use in
33     /// this context means that the existing value of the variable is
34     /// read or modified. e.g., `y` is used in `x = y` but not `x`.
35     /// Note that `DROP(x)` terminators are excluded from this list.
36     first_use_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
37
38     /// Head of a linked list of **drops** of each variable -- these
39     /// are a special category of uses corresponding to the drop that
40     /// we add for each local variable.
41     first_drop_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
42
43     appearances: IndexVec<AppearanceIndex, Appearance>,
44 }
45
46 struct Appearance {
47     point_index: PointIndex,
48     next: Option<AppearanceIndex>,
49 }
50
51 newtype_index!(AppearanceIndex);
52
53 impl vll::LinkElem for Appearance {
54     type LinkIndex = AppearanceIndex;
55
56     fn next(elem: &Self) -> Option<AppearanceIndex> {
57         elem.next
58     }
59 }
60
61 impl LocalUseMap<'me> {
62     crate fn build(
63         liveness_map: &'me NllLivenessMap,
64         elements: &RegionValueElements,
65         mir: &Mir<'_>,
66     ) -> Self {
67         let nones = IndexVec::from_elem_n(None, liveness_map.num_variables());
68         let mut local_use_map = LocalUseMap {
69             liveness_map,
70             first_def_at: nones.clone(),
71             first_use_at: nones.clone(),
72             first_drop_at: nones,
73             appearances: IndexVec::new(),
74         };
75
76         LocalUseMapBuild {
77             local_use_map: &mut local_use_map,
78             elements,
79         }.visit_mir(mir);
80
81         local_use_map
82     }
83
84     crate fn defs(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
85         vll::iter(self.first_def_at[local], &self.appearances)
86             .map(move |aa| self.appearances[aa].point_index)
87     }
88
89     crate fn uses(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
90         vll::iter(self.first_use_at[local], &self.appearances)
91             .map(move |aa| self.appearances[aa].point_index)
92     }
93
94     crate fn drops(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
95         vll::iter(self.first_drop_at[local], &self.appearances)
96             .map(move |aa| self.appearances[aa].point_index)
97     }
98 }
99
100 struct LocalUseMapBuild<'me, 'map: 'me> {
101     local_use_map: &'me mut LocalUseMap<'map>,
102     elements: &'me RegionValueElements,
103 }
104
105 impl LocalUseMapBuild<'_, '_> {
106     fn insert_def(&mut self, local: LiveVar, location: Location) {
107         Self::insert(
108             self.elements,
109             &mut self.local_use_map.first_def_at[local],
110             &mut self.local_use_map.appearances,
111             location,
112         );
113     }
114
115     fn insert_use(&mut self, local: LiveVar, location: Location) {
116         Self::insert(
117             self.elements,
118             &mut self.local_use_map.first_use_at[local],
119             &mut self.local_use_map.appearances,
120             location,
121         );
122     }
123
124     fn insert_drop(&mut self, local: LiveVar, location: Location) {
125         Self::insert(
126             self.elements,
127             &mut self.local_use_map.first_drop_at[local],
128             &mut self.local_use_map.appearances,
129             location,
130         );
131     }
132
133     fn insert(
134         elements: &RegionValueElements,
135         first_appearance: &mut Option<AppearanceIndex>,
136         appearances: &mut IndexVec<AppearanceIndex, Appearance>,
137         location: Location,
138     ) {
139         let point_index = elements.point_from_location(location);
140         let appearance_index = appearances.push(Appearance {
141             point_index,
142             next: *first_appearance,
143         });
144         *first_appearance = Some(appearance_index);
145     }
146 }
147
148 impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> {
149     fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) {
150         if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) {
151             match categorize(context) {
152                 Some(DefUse::Def) => self.insert_def(local_with_region, location),
153                 Some(DefUse::Use) => self.insert_use(local_with_region, location),
154                 Some(DefUse::Drop) => self.insert_drop(local_with_region, location),
155                 _ => (),
156             }
157         }
158     }
159 }