1use std::num::NonZero;
6
7use rustc_data_structures::jobserver::Proxy;
8use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
9use rustc_data_structures::sync::{DynSend, DynSync};
10use rustc_data_structures::unord::UnordMap;
11use rustc_hashes::Hash64;
12use rustc_hir::def_id::DefId;
13use rustc_hir::limit::Limit;
14use rustc_index::Idx;
15use rustc_middle::bug;
16#[expect(unused_imports, reason = "used by doc comments")]
17use rustc_middle::dep_graph::DepKindVTable;
18use rustc_middle::dep_graph::{
19 self, DepContext, DepNode, DepNodeIndex, DepNodeKey, DepsType, HasDepContext,
20 SerializedDepNodeIndex, dep_kinds,
21};
22use rustc_middle::query::on_disk_cache::{
23 AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
24};
25use rustc_middle::query::plumbing::QueryVTable;
26use rustc_middle::query::{
27 Key, QueryCache, QueryContext, QueryJobId, QueryStackDeferred, QueryStackFrame,
28 QueryStackFrameExtra,
29};
30use rustc_middle::ty::codec::TyEncoder;
31use rustc_middle::ty::print::with_reduced_queries;
32use rustc_middle::ty::tls::{self, ImplicitCtxt};
33use rustc_middle::ty::{self, TyCtxt};
34use rustc_query_system::query::QuerySideEffect;
35use rustc_serialize::{Decodable, Encodable};
36use rustc_span::def_id::LOCAL_CRATE;
37
38use crate::error::{QueryOverflow, QueryOverflowNote};
39use crate::execution::{all_inactive, force_query};
40use crate::job::{QueryJobMap, find_dep_kind_root};
41use crate::{QueryDispatcherUnerased, QueryFlags, SemiDynamicQueryDispatcher};
42
43#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for QueryCtxt<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for QueryCtxt<'tcx> {
#[inline]
fn clone(&self) -> QueryCtxt<'tcx> {
let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
*self
}
}Clone)]
46pub struct QueryCtxt<'tcx> {
47 pub tcx: TyCtxt<'tcx>,
48}
49
50impl<'tcx> QueryCtxt<'tcx> {
51 #[inline]
52 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
53 QueryCtxt { tcx }
54 }
55
56 fn depth_limit_error(self, job: QueryJobId) {
57 let job_map = self
58 .collect_active_jobs_from_all_queries(true)
59 .expect("failed to collect active queries");
60 let (info, depth) = find_dep_kind_root(job, job_map);
61
62 let suggested_limit = match self.tcx.recursion_limit() {
63 Limit(0) => Limit(2),
64 limit => limit * 2,
65 };
66
67 self.tcx.sess.dcx().emit_fatal(QueryOverflow {
68 span: info.job.span,
69 note: QueryOverflowNote { desc: info.frame.info.extract().description, depth },
70 suggested_limit,
71 crate_name: self.tcx.crate_name(LOCAL_CRATE),
72 });
73 }
74
75 #[inline]
76 pub(crate) fn next_job_id(self) -> QueryJobId {
77 QueryJobId(
78 NonZero::new(
79 self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
80 )
81 .unwrap(),
82 )
83 }
84
85 #[inline]
86 pub(crate) fn current_query_job(self) -> Option<QueryJobId> {
87 tls::with_related_context(self.tcx, |icx| icx.query)
88 }
89
90 #[inline(always)]
93 pub(crate) fn start_query<R>(
94 self,
95 token: QueryJobId,
96 depth_limit: bool,
97 compute: impl FnOnce() -> R,
98 ) -> R {
99 tls::with_related_context(self.tcx, move |current_icx| {
103 if depth_limit
104 && !self.tcx.recursion_limit().value_within_limit(current_icx.query_depth)
105 {
106 self.depth_limit_error(token);
107 }
108
109 let new_icx = ImplicitCtxt {
111 tcx: self.tcx,
112 query: Some(token),
113 query_depth: current_icx.query_depth + depth_limit as usize,
114 task_deps: current_icx.task_deps,
115 };
116
117 tls::enter_context(&new_icx, compute)
119 })
120 }
121
122 pub fn collect_active_jobs_from_all_queries(
133 self,
134 require_complete: bool,
135 ) -> Result<QueryJobMap<'tcx>, QueryJobMap<'tcx>> {
136 let mut job_map_out = QueryJobMap::default();
137 let mut complete = true;
138
139 for gather_fn in crate::PER_QUERY_GATHER_ACTIVE_JOBS_FNS.iter() {
140 if gather_fn(self.tcx, require_complete, &mut job_map_out).is_none() {
141 complete = false;
142 }
143 }
144
145 if complete { Ok(job_map_out) } else { Err(job_map_out) }
146 }
147}
148
149impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
150 type Deps = DepsType;
151 type DepContext = TyCtxt<'tcx>;
152
153 #[inline]
154 fn dep_context(&self) -> &Self::DepContext {
155 &self.tcx
156 }
157}
158
159impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> {
160 #[inline]
161 fn jobserver_proxy(&self) -> &Proxy {
162 &self.tcx.jobserver_proxy
163 }
164
165 fn load_side_effect(
167 self,
168 prev_dep_node_index: SerializedDepNodeIndex,
169 ) -> Option<QuerySideEffect> {
170 self.tcx
171 .query_system
172 .on_disk_cache
173 .as_ref()
174 .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
175 }
176
177 #[inline(never)]
178 #[cold]
179 fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
180 if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() {
181 c.store_side_effect(dep_node_index, side_effect)
182 }
183 }
184}
185
186pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
187 tcx.dep_graph.try_mark_green(QueryCtxt::new(tcx), dep_node).is_some()
188}
189
190pub(super) fn encode_all_query_results<'tcx>(
191 tcx: TyCtxt<'tcx>,
192 encoder: &mut CacheEncoder<'_, 'tcx>,
193 query_result_index: &mut EncodedDepNodeIndex,
194) {
195 for encode in super::ENCODE_QUERY_RESULTS.iter().copied().flatten() {
196 encode(tcx, encoder, query_result_index);
197 }
198}
199
200pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
201 if tcx.sess().opts.unstable_opts.incremental_verify_ich || truecfg!(debug_assertions) {
202 tcx.sess.time("query_key_hash_verify_all", || {
203 for verify in super::QUERY_KEY_HASH_VERIFY.iter() {
204 verify(tcx);
205 }
206 })
207 }
208}
209
210macro_rules! cycle_error_handling {
211 ([]) => {{
212 rustc_middle::query::CycleErrorHandling::Error
213 }};
214 ([(cycle_fatal) $($rest:tt)*]) => {{
215 rustc_middle::query::CycleErrorHandling::Fatal
216 }};
217 ([(cycle_stash) $($rest:tt)*]) => {{
218 rustc_middle::query::CycleErrorHandling::Stash
219 }};
220 ([(cycle_delay_bug) $($rest:tt)*]) => {{
221 rustc_middle::query::CycleErrorHandling::DelayBug
222 }};
223 ([$other:tt $($modifiers:tt)*]) => {
224 cycle_error_handling!([$($modifiers)*])
225 };
226}
227
228macro_rules! is_anon {
229 ([]) => {{
230 false
231 }};
232 ([(anon) $($rest:tt)*]) => {{
233 true
234 }};
235 ([$other:tt $($modifiers:tt)*]) => {
236 is_anon!([$($modifiers)*])
237 };
238}
239
240macro_rules! is_eval_always {
241 ([]) => {{
242 false
243 }};
244 ([(eval_always) $($rest:tt)*]) => {{
245 true
246 }};
247 ([$other:tt $($modifiers:tt)*]) => {
248 is_eval_always!([$($modifiers)*])
249 };
250}
251
252macro_rules! depth_limit {
253 ([]) => {{
254 false
255 }};
256 ([(depth_limit) $($rest:tt)*]) => {{
257 true
258 }};
259 ([$other:tt $($modifiers:tt)*]) => {
260 depth_limit!([$($modifiers)*])
261 };
262}
263
264macro_rules! feedable {
265 ([]) => {{
266 false
267 }};
268 ([(feedable) $($rest:tt)*]) => {{
269 true
270 }};
271 ([$other:tt $($modifiers:tt)*]) => {
272 feedable!([$($modifiers)*])
273 };
274}
275
276macro_rules! hash_result {
277 ([][$V:ty]) => {{
278 Some(|hcx, result| {
279 let result = rustc_middle::query::erase::restore_val::<$V>(*result);
280 rustc_middle::dep_graph::hash_result(hcx, &result)
281 })
282 }};
283 ([(no_hash) $($rest:tt)*][$V:ty]) => {{
284 None
285 }};
286 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
287 hash_result!([$($modifiers)*][$($args)*])
288 };
289}
290
291macro_rules! call_provider {
292 ([][$tcx:expr, $name:ident, $key:expr]) => {{
293 ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
294 }};
295 ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
296 if let Some(key) = $key.as_local_key() {
297 ($tcx.query_system.fns.local_providers.$name)($tcx, key)
298 } else {
299 ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
300 }
301 }};
302 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
303 call_provider!([$($modifiers)*][$($args)*])
304 };
305}
306
307macro_rules! if_cache_on_disk {
310 ([] $yes:tt $no:tt) => {
311 $no
312 };
313 ([(cache_on_disk) $($rest:tt)*] $yes:tt $no:tt) => {
316 $yes
317 };
318 ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
319 if_cache_on_disk!([$($modifiers)*] $yes $no)
320 };
321}
322
323macro_rules! item_if_cache_on_disk {
326 ([] $($item:tt)*) => {};
327 ([(cache_on_disk) $($rest:tt)*] $($item:tt)*) => {
328 $($item)*
329 };
330 ([$other:tt $($modifiers:tt)*] $($item:tt)*) => {
331 item_if_cache_on_disk! { [$($modifiers)*] $($item)* }
332 };
333}
334
335fn mk_query_stack_frame_extra<'tcx, Cache>(
337 (tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key),
338) -> QueryStackFrameExtra
339where
340 Cache: QueryCache,
341 Cache::Key: Key,
342{
343 let def_id = key.key_as_def_id();
344
345 let reduce_queries = with_reduced_queries();
348
349 let description = {
{
let _guard = ReducedQueriesGuard::new();
{
let _guard = ForcedImplGuard::new();
{
let _guard = NoTrimmedGuard::new();
{
let _guard = NoVisibleGuard::new();
(vtable.description_fn)(tcx, key)
}
}
}
}
}ty::print::with_no_queries!((vtable.description_fn)(tcx, key));
351 let description = if tcx.sess.verbose_internals() {
352 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1} [{0:?}]", vtable.name,
description))
})format!("{description} [{name:?}]", name = vtable.name)
353 } else {
354 description
355 };
356 let span = if vtable.dep_kind == dep_graph::dep_kinds::def_span || reduce_queries {
357 None
360 } else {
361 Some(key.default_span(tcx))
362 };
363
364 let def_kind = if vtable.dep_kind == dep_graph::dep_kinds::def_kind || reduce_queries {
365 None
367 } else {
368 def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
369 };
370 QueryStackFrameExtra::new(description, span, def_kind)
371}
372
373pub(crate) fn create_deferred_query_stack_frame<'tcx, Cache>(
374 tcx: TyCtxt<'tcx>,
375 vtable: &'tcx QueryVTable<'tcx, Cache>,
376 key: Cache::Key,
377) -> QueryStackFrame<QueryStackDeferred<'tcx>>
378where
379 Cache: QueryCache,
380 Cache::Key: Key + DynSend + DynSync,
381{
382 let kind = vtable.dep_kind;
383
384 let hash = tcx.with_stable_hashing_context(|mut hcx| {
385 let mut hasher = StableHasher::new();
386 kind.as_usize().hash_stable(&mut hcx, &mut hasher);
387 key.hash_stable(&mut hcx, &mut hasher);
388 hasher.finish::<Hash64>()
389 });
390
391 let def_id: Option<DefId> = key.key_as_def_id();
392 let def_id_for_ty_in_cycle: Option<DefId> = key.def_id_for_ty_in_cycle();
393
394 let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra);
395 QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
396}
397
398pub(crate) fn encode_query_results<'a, 'tcx, Q, C: QueryCache, const FLAGS: QueryFlags>(
399 query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>,
400 qcx: QueryCtxt<'tcx>,
401 encoder: &mut CacheEncoder<'a, 'tcx>,
402 query_result_index: &mut EncodedDepNodeIndex,
403) where
404 Q: QueryDispatcherUnerased<'tcx, C, FLAGS>,
405 Q::UnerasedValue: Encodable<CacheEncoder<'a, 'tcx>>,
406{
407 let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name());
408
409 if !all_inactive(query.query_state(qcx)) {
::core::panicking::panic("assertion failed: all_inactive(query.query_state(qcx))")
};assert!(all_inactive(query.query_state(qcx)));
410 let cache = query.query_cache(qcx);
411 cache.iter(&mut |key, value, dep_node| {
412 if query.will_cache_on_disk_for_key(qcx.tcx, key) {
413 let dep_node = SerializedDepNodeIndex::new(dep_node.index());
414
415 query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
417
418 encoder.encode_tagged(dep_node, &Q::restore_val(*value));
421 }
422 });
423}
424
425pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
426 query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>,
427 qcx: QueryCtxt<'tcx>,
428) {
429 let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
430
431 let cache = query.query_cache(qcx);
432 let mut map = UnordMap::with_capacity(cache.len());
433 cache.iter(&mut |key, _, _| {
434 let node = DepNode::construct(qcx.tcx, query.dep_kind(), key);
435 if let Some(other_key) = map.insert(node, *key) {
436 ::rustc_middle::util::bug::bug_fmt(format_args!("query key:\n`{0:?}`\nand key:\n`{1:?}`\nmapped to the same dep node:\n{2:?}",
key, other_key, node));bug!(
437 "query key:\n\
438 `{:?}`\n\
439 and key:\n\
440 `{:?}`\n\
441 mapped to the same dep node:\n\
442 {:?}",
443 key,
444 other_key,
445 node
446 );
447 }
448 });
449}
450
451pub(crate) fn try_load_from_on_disk_cache_inner<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
453 query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>,
454 tcx: TyCtxt<'tcx>,
455 dep_node: DepNode,
456) {
457 if true {
if !tcx.dep_graph.is_green(&dep_node) {
::core::panicking::panic("assertion failed: tcx.dep_graph.is_green(&dep_node)")
};
};debug_assert!(tcx.dep_graph.is_green(&dep_node));
458
459 let key = C::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
460 {
::core::panicking::panic_fmt(format_args!("Failed to recover key for {0:?} with hash {1}",
dep_node, dep_node.hash));
}panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
461 });
462 if query.will_cache_on_disk_for_key(tcx, &key) {
463 query.call_query_method(tcx, key);
466 }
467}
468
469pub(crate) fn loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
470 if let Some(cache) = tcx.query_system.on_disk_cache.as_ref() {
471 cache.loadable_from_disk(id)
472 } else {
473 false
474 }
475}
476
477pub(crate) fn try_load_from_disk<'tcx, V>(
478 tcx: TyCtxt<'tcx>,
479 prev_index: SerializedDepNodeIndex,
480 index: DepNodeIndex,
481) -> Option<V>
482where
483 V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
484{
485 let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
486
487 let prof_timer = tcx.prof.incr_cache_loading();
488
489 let value = tcx
493 .dep_graph
494 .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
495
496 prof_timer.finish_with_query_invocation_id(index.into());
497
498 value
499}
500
501pub(crate) fn force_from_dep_node_inner<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
503 query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>,
504 tcx: TyCtxt<'tcx>,
505 dep_node: DepNode,
506) -> bool {
507 if true {
if !(dep_node.kind != dep_kinds::codegen_unit) {
{
::core::panicking::panic_fmt(format_args!("calling force_from_dep_node() on dep_kinds::codegen_unit"));
}
};
};debug_assert!(
521 dep_node.kind != dep_kinds::codegen_unit,
522 "calling force_from_dep_node() on dep_kinds::codegen_unit"
523 );
524
525 if let Some(key) = C::Key::recover(tcx, &dep_node) {
526 force_query(query, QueryCtxt::new(tcx), key, dep_node);
527 true
528 } else {
529 false
530 }
531}
532
533macro_rules! define_queries {
536 (
537 $(
538 $(#[$attr:meta])*
539 [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,
540 )*
541 ) => {
542
543 pub(crate) mod query_impl { $(pub(crate) mod $name {
544 use super::super::*;
545 use std::marker::PhantomData;
546 use ::rustc_middle::query::erase::{self, Erased};
547
548 pub(crate) mod get_query_incr {
549 use super::*;
550
551 #[inline(never)]
554 pub(crate) fn __rust_end_short_backtrace<'tcx>(
555 tcx: TyCtxt<'tcx>,
556 span: Span,
557 key: queries::$name::Key<'tcx>,
558 mode: QueryMode,
559 ) -> Option<Erased<queries::$name::Value<'tcx>>> {
560 #[cfg(debug_assertions)]
561 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
562 execution::get_query_incr(
563 QueryType::query_dispatcher(tcx),
564 QueryCtxt::new(tcx),
565 span,
566 key,
567 mode
568 )
569 }
570 }
571
572 pub(crate) mod get_query_non_incr {
573 use super::*;
574
575 #[inline(never)]
576 pub(crate) fn __rust_end_short_backtrace<'tcx>(
577 tcx: TyCtxt<'tcx>,
578 span: Span,
579 key: queries::$name::Key<'tcx>,
580 __mode: QueryMode,
581 ) -> Option<Erased<queries::$name::Value<'tcx>>> {
582 Some(execution::get_query_non_incr(
583 QueryType::query_dispatcher(tcx),
584 QueryCtxt::new(tcx),
585 span,
586 key,
587 ))
588 }
589 }
590
591 mod invoke_provider_fn {
597 use super::*;
598 use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased};
599
600 #[inline(never)]
601 pub(crate) fn __rust_begin_short_backtrace<'tcx>(
602 tcx: TyCtxt<'tcx>,
603 key: Key<'tcx>,
604 ) -> Erased<Value<'tcx>> {
605 #[cfg(debug_assertions)]
606 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
607
608 let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]);
610
611 rustc_middle::ty::print::with_reduced_queries!({
612 tracing::trace!(?provided_value);
613 });
614
615 provided_to_erased(tcx, provided_value)
618 }
619 }
620
621 pub(crate) fn make_query_vtable<'tcx>()
622 -> QueryVTable<'tcx, queries::$name::Storage<'tcx>>
623 {
624 QueryVTable {
625 name: stringify!($name),
626 eval_always: is_eval_always!([$($modifiers)*]),
627 dep_kind: dep_graph::dep_kinds::$name,
628 cycle_error_handling: cycle_error_handling!([$($modifiers)*]),
629 query_state: std::mem::offset_of!(QueryStates<'tcx>, $name),
630 query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name),
631 will_cache_on_disk_for_key_fn: if_cache_on_disk!([$($modifiers)*] {
632 Some(::rustc_middle::queries::_cache_on_disk_if_fns::$name)
633 } {
634 None
635 }),
636 call_query_method_fn: |tcx, key| {
637 let _ = tcx.$name(key);
640 },
641 invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace,
642 try_load_from_disk_fn: if_cache_on_disk!([$($modifiers)*] {
643 Some(|tcx, key, prev_index, index| {
644 if !::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) {
646 return None;
647 }
648
649 let value: queries::$name::ProvidedValue<'tcx> =
650 $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?;
651
652 Some(queries::$name::provided_to_erased(tcx, value))
654 })
655 } {
656 None
657 }),
658 is_loadable_from_disk_fn: if_cache_on_disk!([$($modifiers)*] {
659 Some(|tcx, key, index| -> bool {
660 ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) &&
661 $crate::plumbing::loadable_from_disk(tcx, index)
662 })
663 } {
664 None
665 }),
666 value_from_cycle_error: |tcx, cycle, guar| {
667 let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar);
668 erase::erase_val(result)
669 },
670 hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
671 format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
672 description_fn: $crate::queries::_description_fns::$name,
673 }
674 }
675
676 #[derive(Copy, Clone, Default)]
677 pub(crate) struct QueryType<'tcx> {
678 data: PhantomData<&'tcx ()>
679 }
680
681 const FLAGS: QueryFlags = QueryFlags {
682 is_anon: is_anon!([$($modifiers)*]),
683 is_depth_limit: depth_limit!([$($modifiers)*]),
684 is_feedable: feedable!([$($modifiers)*]),
685 };
686
687 impl<'tcx> QueryDispatcherUnerased<'tcx, queries::$name::Storage<'tcx>, FLAGS>
688 for QueryType<'tcx>
689 {
690 type UnerasedValue = queries::$name::Value<'tcx>;
691
692 const NAME: &'static &'static str = &stringify!($name);
693
694 #[inline(always)]
695 fn query_dispatcher(tcx: TyCtxt<'tcx>)
696 -> SemiDynamicQueryDispatcher<'tcx, queries::$name::Storage<'tcx>, FLAGS>
697 {
698 SemiDynamicQueryDispatcher {
699 vtable: &tcx.query_system.query_vtables.$name,
700 }
701 }
702
703 #[inline(always)]
704 fn restore_val(value: <queries::$name::Storage<'tcx> as QueryCache>::Value)
705 -> Self::UnerasedValue
706 {
707 erase::restore_val::<queries::$name::Value<'tcx>>(value)
708 }
709 }
710
711 pub(crate) fn gather_active_jobs<'tcx>(
715 tcx: TyCtxt<'tcx>,
716 require_complete: bool,
717 job_map_out: &mut QueryJobMap<'tcx>,
718 ) -> Option<()> {
719 let make_frame = |tcx: TyCtxt<'tcx>, key| {
720 let vtable = &tcx.query_system.query_vtables.$name;
721 $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key)
722 };
723
724 let res = crate::execution::gather_active_jobs_inner(&tcx.query_system.states.$name,
726 tcx,
727 make_frame,
728 require_complete,
729 job_map_out,
730 );
731
732 if res.is_none() {
736 tracing::warn!(
737 "Failed to collect active jobs for query with name `{}`!",
738 stringify!($name)
739 );
740 }
741 res
742 }
743
744 pub(crate) fn alloc_self_profile_query_strings<'tcx>(
745 tcx: TyCtxt<'tcx>,
746 string_cache: &mut QueryKeyStringCache
747 ) {
748 $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
749 tcx,
750 stringify!($name),
751 &tcx.query_system.caches.$name,
752 string_cache,
753 )
754 }
755
756 item_if_cache_on_disk! { [$($modifiers)*]
757 pub(crate) fn encode_query_results<'tcx>(
758 tcx: TyCtxt<'tcx>,
759 encoder: &mut CacheEncoder<'_, 'tcx>,
760 query_result_index: &mut EncodedDepNodeIndex
761 ) {
762 $crate::plumbing::encode_query_results::<
763 query_impl::$name::QueryType<'tcx>,
764 _,
765 _
766 > (
767 query_impl::$name::QueryType::query_dispatcher(tcx),
768 QueryCtxt::new(tcx),
769 encoder,
770 query_result_index,
771 )
772 }
773 }
774
775 pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) {
776 $crate::plumbing::query_key_hash_verify(
777 query_impl::$name::QueryType::query_dispatcher(tcx),
778 QueryCtxt::new(tcx),
779 )
780 }
781 })*}
782
783 pub(crate) fn engine(incremental: bool) -> QueryEngine {
784 if incremental {
785 QueryEngine {
786 $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
787 }
788 } else {
789 QueryEngine {
790 $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
791 }
792 }
793 }
794
795 pub fn make_query_vtables<'tcx>() -> queries::PerQueryVTables<'tcx> {
796 queries::PerQueryVTables {
797 $(
798 $name: query_impl::$name::make_query_vtable(),
799 )*
800 }
801 }
802
803 const PER_QUERY_GATHER_ACTIVE_JOBS_FNS: &[
812 for<'tcx> fn(
813 tcx: TyCtxt<'tcx>,
814 require_complete: bool,
815 job_map_out: &mut QueryJobMap<'tcx>,
816 ) -> Option<()>
817 ] = &[
818 $( $crate::query_impl::$name::gather_active_jobs ),*
819 ];
820
821 const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
822 for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
823 ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
824
825 const ENCODE_QUERY_RESULTS: &[
826 Option<for<'tcx> fn(
827 TyCtxt<'tcx>,
828 &mut CacheEncoder<'_, 'tcx>,
829 &mut EncodedDepNodeIndex)
830 >
831 ] = &[
832 $(
833 if_cache_on_disk!([$($modifiers)*] {
834 Some(query_impl::$name::encode_query_results)
835 } {
836 None
837 })
838 ),*
839 ];
840
841 const QUERY_KEY_HASH_VERIFY: &[
842 for<'tcx> fn(TyCtxt<'tcx>)
843 ] = &[$(query_impl::$name::query_key_hash_verify),*];
844
845 mod _dep_kind_vtable_ctors_for_queries {
847 use ::rustc_middle::dep_graph::DepKindVTable;
848 use $crate::dep_kind_vtables::make_dep_kind_vtable_for_query;
849
850 $(
851 pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> {
853 use $crate::query_impl::$name::QueryType;
854 make_dep_kind_vtable_for_query::<QueryType<'tcx>, _, _>(
855 is_eval_always!([$($modifiers)*]),
856 )
857 }
858 )*
859 }
860 }
861}