1 use crate::dep_graph::DepNodeIndex;
2 use crate::ty::query::plumbing::{QueryLookup, QueryState, QueryStateShard};
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_data_structures::sharded::Sharded;
7 use std::default::Default;
9 use std::marker::PhantomData;
11 pub(crate) trait CacheSelector<K, V> {
12 type Cache: QueryCache<Key = K, Value = V>;
15 pub(crate) trait QueryCache: Default {
18 type Sharded: Default;
20 /// Checks if the query is already computed and in the cache.
21 /// It returns the shard index and a lock guard to the shard,
22 /// which will be used if the query is not in the cache and we need
24 fn lookup<'tcx, R, GetCache, OnHit, OnMiss>(
26 state: &'tcx QueryState<'tcx, Self>,
29 // `on_hit` can be called while holding a lock to the query state shard.
35 &'a mut QueryStateShard<'tcx, Self::Key, Self::Sharded>,
36 ) -> &'a mut Self::Sharded,
37 OnHit: FnOnce(&Self::Value, DepNodeIndex) -> R,
38 OnMiss: FnOnce(Self::Key, QueryLookup<'tcx, Self::Key, Self::Sharded>) -> R;
43 lock_sharded_storage: &mut Self::Sharded,
52 get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
53 f: impl for<'a> FnOnce(
54 Box<dyn Iterator<Item = (&'a Self::Key, &'a Self::Value, DepNodeIndex)> + 'a>,
59 pub struct DefaultCacheSelector;
61 impl<K: Eq + Hash, V: Clone> CacheSelector<K, V> for DefaultCacheSelector {
62 type Cache = DefaultCache<K, V>;
65 pub struct DefaultCache<K, V>(PhantomData<(K, V)>);
67 impl<K, V> Default for DefaultCache<K, V> {
68 fn default() -> Self {
69 DefaultCache(PhantomData)
73 impl<K: Eq + Hash, V: Clone> QueryCache for DefaultCache<K, V> {
76 type Sharded = FxHashMap<K, (V, DepNodeIndex)>;
79 fn lookup<'tcx, R, GetCache, OnHit, OnMiss>(
81 state: &'tcx QueryState<'tcx, Self>,
89 for<'a> Fn(&'a mut QueryStateShard<'tcx, K, Self::Sharded>) -> &'a mut Self::Sharded,
90 OnHit: FnOnce(&V, DepNodeIndex) -> R,
91 OnMiss: FnOnce(K, QueryLookup<'tcx, K, Self::Sharded>) -> R,
93 let mut lookup = state.get_lookup(&key);
94 let lock = &mut *lookup.lock;
96 let result = get_cache(lock).raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key);
98 if let Some((_, value)) = result { on_hit(&value.0, value.1) } else { on_miss(key, lookup) }
105 lock_sharded_storage: &mut Self::Sharded,
110 lock_sharded_storage.insert(key, (value, index));
116 get_shard: impl Fn(&mut L) -> &mut Self::Sharded,
117 f: impl for<'a> FnOnce(Box<dyn Iterator<Item = (&'a K, &'a V, DepNodeIndex)> + 'a>) -> R,
119 let mut shards = shards.lock_shards();
120 let mut shards: Vec<_> = shards.iter_mut().map(|shard| get_shard(shard)).collect();
121 let results = shards.iter_mut().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1));