1use rustc_query_system::dep_graph::{DepKind, DepNodeKey};
5use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached};
6use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
7
8use crate::dep_graph;
9use crate::query::erase::{self, Erasable, Erased};
10use crate::query::plumbing::QueryVTable;
11use crate::ty::TyCtxt;
12
13#[inline(always)]
16pub(crate) fn query_get_at<'tcx, Cache>(
17 tcx: TyCtxt<'tcx>,
18 execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
19 query_cache: &Cache,
20 span: Span,
21 key: Cache::Key,
22) -> Cache::Value
23where
24 Cache: QueryCache,
25{
26 match try_get_cached(tcx, query_cache, &key) {
27 Some(value) => value,
28 None => execute_query(tcx, span, key, QueryMode::Get).unwrap(),
29 }
30}
31
32#[inline]
35pub(crate) fn query_ensure<'tcx, Cache>(
36 tcx: TyCtxt<'tcx>,
37 execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
38 query_cache: &Cache,
39 key: Cache::Key,
40 check_cache: bool,
41) where
42 Cache: QueryCache,
43{
44 if try_get_cached(tcx, query_cache, &key).is_none() {
45 execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache });
46 }
47}
48
49#[inline]
52pub(crate) fn query_ensure_error_guaranteed<'tcx, Cache, T>(
53 tcx: TyCtxt<'tcx>,
54 execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
55 query_cache: &Cache,
56 key: Cache::Key,
57 check_cache: bool,
58) -> Result<(), ErrorGuaranteed>
59where
60 Cache: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
61 Result<T, ErrorGuaranteed>: Erasable,
62{
63 if let Some(res) = try_get_cached(tcx, query_cache, &key) {
64 erase::restore_val(res).map(drop)
65 } else {
66 execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache })
67 .map(erase::restore_val)
68 .map(|res| res.map(drop))
69 .unwrap_or(Ok(()))
76 }
77}
78
79pub(crate) fn query_feed<'tcx, Cache>(
81 tcx: TyCtxt<'tcx>,
82 dep_kind: DepKind,
83 query_vtable: &QueryVTable<'tcx, Cache>,
84 cache: &Cache,
85 key: Cache::Key,
86 value: Cache::Value,
87) where
88 Cache: QueryCache,
89 Cache::Key: DepNodeKey<TyCtxt<'tcx>>,
90{
91 let format_value = query_vtable.format_value;
92
93 match try_get_cached(tcx, cache, &key) {
95 Some(old) => {
96 if let Some(hasher_fn) = query_vtable.hash_result {
100 let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| {
101 (hasher_fn(hcx, &old), hasher_fn(hcx, &value))
102 });
103 if old_hash != value_hash {
104 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!(
108 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
109 old value: {old}\nnew value: {value}",
110 old = format_value(&old),
111 value = format_value(&value),
112 ));
113 }
114 } else {
115 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!(
119 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\
120 old value: {old}\nnew value: {value}",
121 old = format_value(&old),
122 value = format_value(&value),
123 )
124 }
125 }
126 None => {
127 let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key);
130 let dep_node_index = tcx.dep_graph.with_feed_task(
131 dep_node,
132 tcx,
133 &value,
134 query_vtable.hash_result,
135 query_vtable.format_value,
136 );
137 cache.complete(key, value, dep_node_index);
138 }
139 }
140}