1use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
5
6use crate::dep_graph;
7use crate::dep_graph::{DepKind, DepNodeKey};
8use crate::query::erase::{self, Erasable, Erased};
9use crate::query::plumbing::QueryVTable;
10use crate::query::{EnsureMode, QueryCache, QueryMode};
11use crate::ty::TyCtxt;
12
13#[inline(always)]
18fn try_get_cached<'tcx, C>(tcx: TyCtxt<'tcx>, cache: &C, key: C::Key) -> Option<C::Value>
19where
20 C: QueryCache,
21{
22 match cache.lookup(&key) {
23 Some((value, index)) => {
24 tcx.prof.query_cache_hit(index.into());
25 tcx.dep_graph.read_index(index);
26 Some(value)
27 }
28 None => None,
29 }
30}
31
32#[inline(always)]
35pub(crate) fn query_get_at<'tcx, C>(
36 tcx: TyCtxt<'tcx>,
37 span: Span,
38 query: &'tcx QueryVTable<'tcx, C>,
39 key: C::Key,
40) -> C::Value
41where
42 C: QueryCache,
43{
44 match try_get_cached(tcx, &query.cache, key) {
45 Some(value) => value,
46 None => (query.execute_query_fn)(tcx, span, key, QueryMode::Get).unwrap(),
47 }
48}
49
50#[inline]
53pub(crate) fn query_ensure_ok_or_done<'tcx, C>(
54 tcx: TyCtxt<'tcx>,
55 query: &'tcx QueryVTable<'tcx, C>,
56 key: C::Key,
57 ensure_mode: EnsureMode,
58) where
59 C: QueryCache,
60{
61 match try_get_cached(tcx, &query.cache, key) {
62 Some(_value) => {}
63 None => {
64 (query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode });
65 }
66 }
67}
68
69#[inline]
72pub(crate) fn query_ensure_result<'tcx, C, T>(
73 tcx: TyCtxt<'tcx>,
74 query: &'tcx QueryVTable<'tcx, C>,
75 key: C::Key,
76) -> Result<(), ErrorGuaranteed>
77where
78 C: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
79 Result<T, ErrorGuaranteed>: Erasable,
80{
81 match try_get_cached(tcx, &query.cache, key) {
82 Some(value) => erase::restore_val(value).map(drop),
83 None => (query.execute_query_fn)(
84 tcx,
85 DUMMY_SP,
86 key,
87 QueryMode::Ensure { ensure_mode: EnsureMode::Ok },
88 )
89 .map(erase::restore_val)
90 .map(|value| value.map(drop))
91 .unwrap_or(Ok(())),
98 }
99}
100
101pub(crate) fn query_feed<'tcx, C>(
103 tcx: TyCtxt<'tcx>,
104 dep_kind: DepKind,
105 query_vtable: &QueryVTable<'tcx, C>,
106 key: C::Key,
107 value: C::Value,
108) where
109 C: QueryCache,
110 C::Key: DepNodeKey<'tcx>,
111{
112 let format_value = query_vtable.format_value;
113
114 match try_get_cached(tcx, &query_vtable.cache, key) {
116 Some(old) => {
117 if let Some(hash_value_fn) = query_vtable.hash_value_fn {
121 let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| {
122 (hash_value_fn(hcx, &old), hash_value_fn(hcx, &value))
123 });
124 if old_hash != value_hash {
125 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), dep_kind, key))
})format!(
129 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
130 old value: {old}\nnew value: {value}",
131 old = format_value(&old),
132 value = format_value(&value),
133 ));
134 }
135 } else {
136 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), dep_kind, key))bug!(
140 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
141 old value: {old}\nnew value: {value}",
142 old = format_value(&old),
143 value = format_value(&value),
144 )
145 }
146 }
147 None => {
148 let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key);
151 let dep_node_index = tcx.dep_graph.with_feed_task(
152 dep_node,
153 tcx,
154 &value,
155 query_vtable.hash_value_fn,
156 query_vtable.format_value,
157 );
158 query_vtable.cache.complete(key, value, dep_node_index);
159 }
160 }
161}