1use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
5
6use crate::dep_graph;
7use crate::dep_graph::DepNodeKey;
8use crate::query::erase::{self, Erasable, Erased};
9use crate::query::{QueryCache, QueryMode, QueryVTable};
10use crate::ty::TyCtxt;
11
12#[inline(always)]
17fn try_get_cached<'tcx, C>(tcx: TyCtxt<'tcx>, cache: &C, key: C::Key) -> Option<C::Value>
18where
19 C: QueryCache,
20{
21 match cache.lookup(&key) {
22 Some((value, index)) => {
23 tcx.prof.query_cache_hit(index.into());
24 tcx.dep_graph.read_index(index);
25 Some(value)
26 }
27 None => None,
28 }
29}
30
31#[inline(always)]
34pub(crate) fn query_get_at<'tcx, C>(
35 tcx: TyCtxt<'tcx>,
36 span: Span,
37 query: &'tcx QueryVTable<'tcx, C>,
38 key: C::Key,
39) -> C::Value
40where
41 C: QueryCache,
42{
43 match try_get_cached(tcx, &query.cache, key) {
44 Some(value) => value,
45 None => (query.execute_query_fn)(tcx, span, key, QueryMode::Get).unwrap(),
46 }
47}
48
49#[inline]
51pub(crate) fn query_ensure_ok<'tcx, C>(
52 tcx: TyCtxt<'tcx>,
53 query: &'tcx QueryVTable<'tcx, C>,
54 key: C::Key,
55) where
56 C: QueryCache,
57{
58 match try_get_cached(tcx, &query.cache, key) {
59 Some(_value) => {}
60 None => {
61 (query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::EnsureOk);
62 }
63 }
64}
65
66#[inline]
69pub(crate) fn query_ensure_result<'tcx, C, T>(
70 tcx: TyCtxt<'tcx>,
71 query: &'tcx QueryVTable<'tcx, C>,
72 key: C::Key,
73) -> Result<(), ErrorGuaranteed>
74where
75 C: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
76 Result<T, ErrorGuaranteed>: Erasable,
77{
78 let convert = |value: Erased<Result<T, ErrorGuaranteed>>| -> Result<(), ErrorGuaranteed> {
79 match erase::restore_val(value) {
80 Ok(_) => Ok(()),
81 Err(guar) => Err(guar),
82 }
83 };
84
85 match try_get_cached(tcx, &query.cache, key) {
86 Some(value) => convert(value),
87 None => {
88 match (query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::EnsureOk) {
89 Some(res) => convert(res),
91
92 None => Ok(()),
99 }
100 }
101 }
102}
103
104pub(crate) fn query_feed<'tcx, C>(
107 tcx: TyCtxt<'tcx>,
108 query: &'tcx QueryVTable<'tcx, C>,
109 key: C::Key,
110 value: C::Value,
111) where
112 C: QueryCache,
113 C::Key: DepNodeKey<'tcx>,
114{
115 let format_value = query.format_value;
116
117 match try_get_cached(tcx, &query.cache, key) {
119 Some(old) => {
120 if let Some(hash_value_fn) = query.hash_value_fn {
124 let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| {
125 (hash_value_fn(hcx, &old), hash_value_fn(hcx, &value))
126 });
127 if old_hash != value_hash {
128 tcx.dcx().delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Trying to feed an already recorded value for query {2:?} key={3:?}:\nold value: {0}\nnew value: {1}",
format_value(&old), format_value(&value), query, key))
})format!(
132 "Trying to feed an already recorded value for query {query:?} key={key:?}:\n\
133 old value: {old}\nnew value: {value}",
134 old = format_value(&old),
135 value = format_value(&value),
136 ));
137 }
138 } else {
139 crate::util::bug::bug_fmt(format_args!("Trying to feed an already recorded value for query {2:?} key={3:?}:\nold value: {0}\nnew value: {1}",
format_value(&old), format_value(&value), query, key))bug!(
143 "Trying to feed an already recorded value for query {query:?} key={key:?}:\n\
144 old value: {old}\nnew value: {value}",
145 old = format_value(&old),
146 value = format_value(&value),
147 )
148 }
149 }
150 None => {
151 let dep_node = dep_graph::DepNode::construct(tcx, query.dep_kind, &key);
154 let dep_node_index = tcx.dep_graph.with_feed_task(
155 dep_node,
156 tcx,
157 &value,
158 query.hash_value_fn,
159 query.format_value,
160 );
161 query.cache.complete(key, value, dep_node_index);
162 }
163 }
164}