miri/borrow_tracker/tree_borrows/
unimap.rs1#![allow(dead_code)]
14
15use std::fmt::Debug;
16use std::hash::Hash;
17use std::mem;
18
19use rustc_data_structures::fx::FxHashMap;
20
21use crate::helpers::ToUsize;
22
23#[derive(Clone, Copy, PartialEq, Eq)]
25pub struct UniIndex {
26 idx: u32,
27}
28impl Debug for UniIndex {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 self.idx.fmt(f)
31 }
32}
33
34#[derive(Debug, Clone, Default)]
36pub struct UniKeyMap<K> {
37 mapping: FxHashMap<K, u32>,
42 deassigned: Vec<u32>,
45}
46
47#[derive(Debug, Clone, Eq)]
49pub struct UniValMap<V> {
50 data: Vec<Option<V>>,
53}
54
55impl<V: PartialEq> UniValMap<V> {
56 pub fn identical(&self, other: &Self) -> bool {
60 self.data == other.data
61 }
62
63 pub fn equivalent(&self, other: &Self) -> bool {
66 let min_len = self.data.len().min(other.data.len());
67 self.data[min_len..].iter().all(Option::is_none)
68 && other.data[min_len..].iter().all(Option::is_none)
69 && (self.data[..min_len] == other.data[..min_len])
70 }
71}
72
73impl<V: PartialEq> PartialEq for UniValMap<V> {
74 fn eq(&self, other: &Self) -> bool {
80 self.equivalent(other)
81 }
82}
83
84impl<V> Default for UniValMap<V> {
85 fn default() -> Self {
86 Self { data: Vec::default() }
87 }
88}
89
90impl<K> UniKeyMap<K>
91where
92 K: Hash + Eq,
93{
94 pub fn len(&self) -> usize {
96 self.mapping.len()
97 }
98
99 pub fn contains_key(&self, key: &K) -> bool {
101 self.mapping.contains_key(key)
102 }
103
104 #[track_caller]
108 pub fn insert(&mut self, key: K) -> UniIndex {
109 let idx = self.deassigned.pop().unwrap_or_else(|| {
112 self.mapping.len().try_into().expect("UniMap ran out of useable keys")
115 });
116 if self.mapping.insert(key, idx).is_some() {
117 panic!(
118 "This key is already assigned to a different index; either use `get_or_insert` instead if you care about this data, or first call `remove` to undo the preexisting assignment."
119 );
120 };
121 UniIndex { idx }
122 }
123
124 pub fn get(&self, key: &K) -> Option<UniIndex> {
126 self.mapping.get(key).map(|&idx| UniIndex { idx })
127 }
128
129 pub fn get_or_insert(&mut self, key: K) -> UniIndex {
132 self.get(&key).unwrap_or_else(|| self.insert(key))
133 }
134
135 pub fn remove(&mut self, key: &K) {
160 if let Some(idx) = self.mapping.remove(key) {
161 self.deassigned.push(idx);
162 }
163 }
164}
165
166impl<V> UniValMap<V> {
167 pub fn contains_idx(&self, idx: UniIndex) -> bool {
169 self.data.get(idx.idx.to_usize()).and_then(Option::as_ref).is_some()
170 }
171
172 fn extend_to_length(&mut self, len: usize) {
174 if len > self.data.len() {
175 let nb = len - self.data.len();
176 self.data.reserve(nb);
177 for _ in 0..nb {
178 self.data.push(None);
179 }
180 }
181 }
182
183 pub fn insert(&mut self, idx: UniIndex, val: V) {
185 self.extend_to_length(idx.idx.to_usize() + 1);
186 self.data[idx.idx.to_usize()] = Some(val)
187 }
188
189 pub fn get(&self, idx: UniIndex) -> Option<&V> {
191 self.data.get(idx.idx.to_usize()).and_then(Option::as_ref)
192 }
193
194 pub fn get_mut(&mut self, idx: UniIndex) -> Option<&mut V> {
196 self.data.get_mut(idx.idx.to_usize()).and_then(Option::as_mut)
197 }
198
199 pub fn remove(&mut self, idx: UniIndex) -> Option<V> {
203 if idx.idx.to_usize() >= self.data.len() {
204 return None;
205 }
206 let mut res = None;
207 mem::swap(&mut res, &mut self.data[idx.idx.to_usize()]);
208 res
209 }
210
211 pub fn is_empty(&self) -> bool {
213 self.data.iter().all(|v| v.is_none())
214 }
215
216 pub fn iter(&self) -> impl Iterator<Item = (UniIndex, &V)> {
218 self.data
219 .iter()
220 .enumerate()
221 .filter_map(|(i, v)| v.as_ref().map(|r| (UniIndex { idx: i.try_into().unwrap() }, r)))
222 }
223}
224
225pub struct UniEntry<'a, V> {
227 inner: &'a mut Option<V>,
228}
229
230impl<'a, V> UniValMap<V> {
231 pub fn entry(&'a mut self, idx: UniIndex) -> UniEntry<'a, V> {
233 self.extend_to_length(idx.idx.to_usize() + 1);
234 UniEntry { inner: &mut self.data[idx.idx.to_usize()] }
235 }
236}
237
238impl<'a, V> UniEntry<'a, V> {
239 pub fn or_insert(&mut self, default: V) -> &mut V {
241 if self.inner.is_none() {
242 *self.inner = Some(default);
243 }
244 self.inner.as_mut().unwrap()
245 }
246
247 pub fn get(&self) -> Option<&V> {
248 self.inner.as_ref()
249 }
250}
251
252mod tests {
253 use super::*;
254
255 #[test]
256 fn extend_to_length() {
257 let mut km = UniValMap::<char>::default();
258 km.extend_to_length(10);
259 assert!(km.data.len() == 10);
260 km.extend_to_length(0);
261 assert!(km.data.len() == 10);
262 km.extend_to_length(10);
263 assert!(km.data.len() == 10);
264 km.extend_to_length(11);
265 assert!(km.data.len() == 11);
266 }
267
268 #[derive(Default)]
269 struct MapWitness<K, V> {
270 key: UniKeyMap<K>,
271 val: UniValMap<V>,
272 map: FxHashMap<K, V>,
273 }
274
275 impl<K, V> MapWitness<K, V>
276 where
277 K: Copy + Hash + Eq,
278 V: Copy + Eq + std::fmt::Debug,
279 {
280 fn insert(&mut self, k: K, v: V) {
281 let i = self.key.get_or_insert(k);
283 self.val.insert(i, v);
284 self.map.insert(k, v);
286 }
288
289 fn get(&self, k: &K) {
290 let v1 = self.key.get(k).and_then(|i| self.val.get(i));
292 let v2 = self.map.get(k);
294 assert_eq!(v1, v2);
296 }
297
298 fn get_mut(&mut self, k: &K) {
299 let v1 = self.key.get(k).and_then(|i| self.val.get_mut(i));
301 let v2 = self.map.get_mut(k);
303 assert_eq!(v1, v2);
305 }
306 fn remove(&mut self, k: &K) {
307 if let Some(i) = self.key.get(k) {
309 self.val.remove(i);
310 }
311 self.key.remove(k);
312 self.map.remove(k);
314 }
316 }
317
318 #[test]
319 fn consistency_small() {
320 let mut m = MapWitness::<u64, char>::default();
321 m.insert(1, 'a');
322 m.insert(2, 'b');
323 m.get(&1);
324 m.get_mut(&2);
325 m.remove(&2);
326 m.insert(1, 'c');
327 m.get(&1);
328 m.insert(3, 'd');
329 m.insert(4, 'e');
330 m.insert(4, 'f');
331 m.get(&2);
332 m.get(&3);
333 m.get(&4);
334 m.get(&5);
335 m.remove(&100);
336 m.get_mut(&100);
337 m.get(&100);
338 }
339
340 #[test]
341 fn consistency_large() {
342 use std::collections::hash_map::DefaultHasher;
343 use std::hash::{Hash, Hasher};
344 let mut hasher = DefaultHasher::new();
345 let mut map = MapWitness::<u64, u64>::default();
346 for i in 0..1000 {
347 i.hash(&mut hasher);
348 let rng = hasher.finish();
349 let op = rng.is_multiple_of(3);
350 let key = (rng / 2) % 50;
351 let val = (rng / 100) % 1000;
352 if op {
353 map.insert(key, val);
354 } else {
355 map.get(&key);
356 }
357 }
358 }
359}