1use std::fmt::Debug;
5
6use rustc_data_structures::fingerprint::Fingerprint;
7use rustc_query_system::dep_graph::{DepKind, DepNodeParams};
8use rustc_query_system::ich::StableHashingContext;
9use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached};
10use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
11
12use crate::dep_graph;
13use crate::query::IntoQueryParam;
14use crate::query::erase::{self, Erase, EraseType};
15use crate::ty::TyCtxt;
16
17#[inline(always)]
20pub(crate) fn query_get_at<'tcx, Cache>(
21 tcx: TyCtxt<'tcx>,
22 execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
23 query_cache: &Cache,
24 span: Span,
25 key: Cache::Key,
26) -> Cache::Value
27where
28 Cache: QueryCache,
29{
30 let key = key.into_query_param();
31 match try_get_cached(tcx, query_cache, &key) {
32 Some(value) => value,
33 None => execute_query(tcx, span, key, QueryMode::Get).unwrap(),
34 }
35}
36
37#[inline]
40pub(crate) fn query_ensure<'tcx, Cache>(
41 tcx: TyCtxt<'tcx>,
42 execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
43 query_cache: &Cache,
44 key: Cache::Key,
45 check_cache: bool,
46) where
47 Cache: QueryCache,
48{
49 let key = key.into_query_param();
50 if try_get_cached(tcx, query_cache, &key).is_none() {
51 execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache });
52 }
53}
54
55#[inline]
58pub(crate) fn query_ensure_error_guaranteed<'tcx, Cache, T>(
59 tcx: TyCtxt<'tcx>,
60 execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
61 query_cache: &Cache,
62 key: Cache::Key,
63 check_cache: bool,
64) -> Result<(), ErrorGuaranteed>
65where
66 Cache: QueryCache<Value = Erase<Result<T, ErrorGuaranteed>>>,
67 Result<T, ErrorGuaranteed>: EraseType,
68{
69 let key = key.into_query_param();
70 if let Some(res) = try_get_cached(tcx, query_cache, &key) {
71 erase::restore(res).map(drop)
72 } else {
73 execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache })
74 .map(erase::restore)
75 .map(|res| res.map(drop))
76 .unwrap_or(Ok(()))
83 }
84}
85
86pub(crate) fn query_feed<'tcx, Cache, Value>(
88 tcx: TyCtxt<'tcx>,
89 dep_kind: DepKind,
90 hasher: Option<fn(&mut StableHashingContext<'_>, &Value) -> Fingerprint>,
91 cache: &Cache,
92 key: Cache::Key,
93 erased: Erase<Value>,
94) where
95 Cache: QueryCache<Value = Erase<Value>>,
96 Cache::Key: DepNodeParams<TyCtxt<'tcx>>,
97 Value: EraseType + Debug,
98{
99 let value = erase::restore::<Value>(erased);
100
101 match try_get_cached(tcx, cache, &key) {
102 Some(old) => {
103 let old = erase::restore::<Value>(old);
104 if let Some(hasher) = hasher {
105 let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx
106 .with_stable_hashing_context(|mut hcx| {
107 (hasher(&mut hcx, &value), hasher(&mut hcx, &old))
108 });
109 if old_hash != value_hash {
110 tcx.dcx().delayed_bug(format!(
114 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
115 old value: {old:?}\nnew value: {value:?}",
116 ));
117 }
118 } else {
119 bug!(
123 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
124 old value: {old:?}\nnew value: {value:?}",
125 )
126 }
127 }
128 None => {
129 let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key);
130 let dep_node_index = tcx.dep_graph.with_feed_task(dep_node, tcx, &value, hasher);
131 cache.complete(key, erased, dep_node_index);
132 }
133 }
134}