rustc_type_ir/data_structures/
delayed_map.rs

1use std::hash::Hash;
2
3use crate::data_structures::{HashMap, HashSet};
4
5const CACHE_CUTOFF: u32 = 32;
6
7/// A hashmap which only starts hashing after ignoring the first few inputs.
8///
9/// This is used in type folders as in nearly all cases caching is not worth it
10/// as nearly all folded types are tiny. However, there are very rare incredibly
11/// large types for which caching is necessary to avoid hangs.
12#[derive(Debug)]
13pub struct DelayedMap<K, V> {
14    cache: HashMap<K, V>,
15    count: u32,
16}
17
18impl<K, V> Default for DelayedMap<K, V> {
19    fn default() -> Self {
20        DelayedMap { cache: Default::default(), count: 0 }
21    }
22}
23
24impl<K: Hash + Eq, V> DelayedMap<K, V> {
25    #[inline(always)]
26    pub fn insert(&mut self, key: K, value: V) -> bool {
27        if self.count >= CACHE_CUTOFF {
28            self.cold_insert(key, value)
29        } else {
30            self.count += 1;
31            true
32        }
33    }
34
35    #[cold]
36    #[inline(never)]
37    fn cold_insert(&mut self, key: K, value: V) -> bool {
38        self.cache.insert(key, value).is_none()
39    }
40
41    #[inline(always)]
42    pub fn get(&self, key: &K) -> Option<&V> {
43        if self.cache.is_empty() { None } else { self.cold_get(key) }
44    }
45
46    #[cold]
47    #[inline(never)]
48    fn cold_get(&self, key: &K) -> Option<&V> {
49        self.cache.get(key)
50    }
51}
52
53#[derive(Debug)]
54pub struct DelayedSet<T> {
55    cache: HashSet<T>,
56    count: u32,
57}
58
59impl<T> Default for DelayedSet<T> {
60    fn default() -> Self {
61        DelayedSet { cache: Default::default(), count: 0 }
62    }
63}
64
65impl<T: Hash + Eq> DelayedSet<T> {
66    #[inline(always)]
67    pub fn insert(&mut self, value: T) -> bool {
68        if self.count >= CACHE_CUTOFF {
69            self.cold_insert(value)
70        } else {
71            self.count += 1;
72            true
73        }
74    }
75
76    #[cold]
77    #[inline(never)]
78    fn cold_insert(&mut self, value: T) -> bool {
79        self.cache.insert(value)
80    }
81
82    #[inline(always)]
83    pub fn contains(&self, value: &T) -> bool {
84        !self.cache.is_empty() && self.cold_contains(value)
85    }
86
87    #[cold]
88    #[inline(never)]
89    fn cold_contains(&self, value: &T) -> bool {
90        self.cache.contains(value)
91    }
92}