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