rustc_borrowck/type_check/liveness/
local_use_map.rs1use rustc_index::IndexVec;
2use rustc_middle::mir::visit::{PlaceContext, Visitor};
3use rustc_middle::mir::{Body, Local, Location};
4use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
5
6use crate::def_use::{self, DefUse};
7
8pub(crate) struct LocalUseMap {
21 first_def_at: IndexVec<Local, Option<AppearanceIndex>>,
27
28 first_use_at: IndexVec<Local, Option<AppearanceIndex>>,
33
34 first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
38
39 appearances: Appearances,
40}
41
42type Appearances = IndexVec<AppearanceIndex, Appearance>;
44
45struct Appearance {
46 point_index: PointIndex,
47 next: Option<AppearanceIndex>,
48}
49
50rustc_index::newtype_index! {
51 pub struct AppearanceIndex {}
52}
53
54fn appearances_iter(
55 first: Option<AppearanceIndex>,
56 appearances: &Appearances,
57) -> impl Iterator<Item = AppearanceIndex> {
58 AppearancesIter { appearances, current: first }
59}
60
61struct AppearancesIter<'a> {
63 appearances: &'a Appearances,
64 current: Option<AppearanceIndex>,
65}
66
67impl<'a> Iterator for AppearancesIter<'a> {
68 type Item = AppearanceIndex;
69
70 fn next(&mut self) -> Option<AppearanceIndex> {
71 if let Some(c) = self.current {
72 self.current = self.appearances[c].next;
73 Some(c)
74 } else {
75 None
76 }
77 }
78}
79
80impl LocalUseMap {
83 pub(crate) fn build(
84 live_locals: &[Local],
85 location_map: &DenseLocationMap,
86 body: &Body<'_>,
87 ) -> Self {
88 let nones = IndexVec::from_elem(None, &body.local_decls);
89 let mut local_use_map = LocalUseMap {
90 first_def_at: nones.clone(),
91 first_use_at: nones.clone(),
92 first_drop_at: nones,
93 appearances: IndexVec::new(),
94 };
95
96 if live_locals.is_empty() {
97 return local_use_map;
98 }
99
100 let mut locals_with_use_data: IndexVec<Local, bool> =
101 IndexVec::from_elem(false, &body.local_decls);
102 live_locals.iter().for_each(|&local| locals_with_use_data[local] = true);
103
104 LocalUseMapBuild { local_use_map: &mut local_use_map, location_map, locals_with_use_data }
105 .visit_body(body);
106
107 local_use_map
108 }
109
110 pub(crate) fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> {
111 appearances_iter(self.first_def_at[local], &self.appearances)
112 .map(move |aa| self.appearances[aa].point_index)
113 }
114
115 pub(crate) fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> {
116 appearances_iter(self.first_use_at[local], &self.appearances)
117 .map(move |aa| self.appearances[aa].point_index)
118 }
119
120 pub(crate) fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> {
121 appearances_iter(self.first_drop_at[local], &self.appearances)
122 .map(move |aa| self.appearances[aa].point_index)
123 }
124}
125
126struct LocalUseMapBuild<'me> {
127 local_use_map: &'me mut LocalUseMap,
128 location_map: &'me DenseLocationMap,
129
130 locals_with_use_data: IndexVec<Local, bool>,
138}
139
140impl Visitor<'_> for LocalUseMapBuild<'_> {
141 fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
142 if self.locals_with_use_data[local]
143 && let Some(def_use) = def_use::categorize(context)
144 {
145 let first_appearance = match def_use {
146 DefUse::Def => &mut self.local_use_map.first_def_at[local],
147 DefUse::Use => &mut self.local_use_map.first_use_at[local],
148 DefUse::Drop => &mut self.local_use_map.first_drop_at[local],
149 };
150 let point_index = self.location_map.point_from_location(location);
151 let appearance_index = self
152 .local_use_map
153 .appearances
154 .push(Appearance { point_index, next: *first_appearance });
155 *first_appearance = Some(appearance_index);
156 }
157 }
158}