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::{EnsureMode, 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]
52pub(crate) fn query_ensure_ok_or_done<'tcx, C>(
53 tcx: TyCtxt<'tcx>,
54 query: &'tcx QueryVTable<'tcx, C>,
55 key: C::Key,
56 ensure_mode: EnsureMode,
57) where
58 C: QueryCache,
59{
60 match try_get_cached(tcx, &query.cache, key) {
61 Some(_value) => {}
62 None => {
63 (query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode });
64 }
65 }
66}
67
68#[inline]
71pub(crate) fn query_ensure_result<'tcx, C, T>(
72 tcx: TyCtxt<'tcx>,
73 query: &'tcx QueryVTable<'tcx, C>,
74 key: C::Key,
75) -> Result<(), ErrorGuaranteed>
76where
77 C: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
78 Result<T, ErrorGuaranteed>: Erasable,
79{
80 let convert = |value: Erased<Result<T, ErrorGuaranteed>>| -> Result<(), ErrorGuaranteed> {
81 match erase::restore_val(value) {
82 Ok(_) => Ok(()),
83 Err(guar) => Err(guar),
84 }
85 };
86
87 match try_get_cached(tcx, &query.cache, key) {
88 Some(value) => convert(value),
89 None => {
90 match (query.execute_query_fn)(
91 tcx,
92 DUMMY_SP,
93 key,
94 QueryMode::Ensure { ensure_mode: EnsureMode::Ok },
95 ) {
96 Some(res) => convert(res),
98
99 None => Ok(()),
106 }
107 }
108 }
109}
110
111pub(crate) fn query_feed<'tcx, C>(
114 tcx: TyCtxt<'tcx>,
115 query: &'tcx QueryVTable<'tcx, C>,
116 key: C::Key,
117 value: C::Value,
118) where
119 C: QueryCache,
120 C::Key: DepNodeKey<'tcx>,
121{
122 let format_value = query.format_value;
123
124 match try_get_cached(tcx, &query.cache, key) {
126 Some(old) => {
127 if let Some(hash_value_fn) = query.hash_value_fn {
131 let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| {
132 (hash_value_fn(hcx, &old), hash_value_fn(hcx, &value))
133 });
134 if old_hash != value_hash {
135 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!(
139 "Trying to feed an already recorded value for query {query:?} key={key:?}:\n\
140 old value: {old}\nnew value: {value}",
141 old = format_value(&old),
142 value = format_value(&value),
143 ));
144 }
145 } else {
146 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!(
150 "Trying to feed an already recorded value for query {query:?} key={key:?}:\n\
151 old value: {old}\nnew value: {value}",
152 old = format_value(&old),
153 value = format_value(&value),
154 )
155 }
156 }
157 None => {
158 let dep_node = dep_graph::DepNode::construct(tcx, query.dep_kind, &key);
161 let dep_node_index = tcx.dep_graph.with_feed_task(
162 dep_node,
163 tcx,
164 &value,
165 query.hash_value_fn,
166 query.format_value,
167 );
168 query.cache.complete(key, value, dep_node_index);
169 }
170 }
171}