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::limit::Limit;
13use rustc_index::Idx;
14use rustc_middle::bug;
15use rustc_middle::dep_graph::{
16 self, DepContext, DepKind, DepKindVTable, DepNode, DepNodeIndex, SerializedDepNodeIndex,
17 dep_kinds,
18};
19use rustc_middle::query::Key;
20use rustc_middle::query::on_disk_cache::{
21 AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
22};
23use rustc_middle::ty::codec::TyEncoder;
24use rustc_middle::ty::print::with_reduced_queries;
25use rustc_middle::ty::tls::{self, ImplicitCtxt};
26use rustc_middle::ty::{self, TyCtxt};
27use rustc_query_system::dep_graph::{DepNodeParams, FingerprintStyle, HasDepContext};
28use rustc_query_system::ich::StableHashingContext;
29use rustc_query_system::query::{
30 QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect,
31 QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query,
32};
33use rustc_query_system::{QueryOverflow, QueryOverflowNote};
34use rustc_serialize::{Decodable, Encodable};
35use rustc_span::def_id::LOCAL_CRATE;
36
37use crate::QueryDispatcherUnerased;
38
39#[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)]
42pub struct QueryCtxt<'tcx> {
43 pub tcx: TyCtxt<'tcx>,
44}
45
46impl<'tcx> QueryCtxt<'tcx> {
47 #[inline]
48 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
49 QueryCtxt { tcx }
50 }
51
52 fn depth_limit_error(self, job: QueryJobId) {
53 let query_map = self
54 .collect_active_jobs_from_all_queries(true)
55 .expect("failed to collect active queries");
56 let (info, depth) = job.find_dep_kind_root(query_map);
57
58 let suggested_limit = match self.tcx.recursion_limit() {
59 Limit(0) => Limit(2),
60 limit => limit * 2,
61 };
62
63 self.tcx.sess.dcx().emit_fatal(QueryOverflow {
64 span: info.job.span,
65 note: QueryOverflowNote { desc: info.frame.info.extract().description, depth },
66 suggested_limit,
67 crate_name: self.tcx.crate_name(LOCAL_CRATE),
68 });
69 }
70}
71
72impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
73 type Deps = rustc_middle::dep_graph::DepsType;
74 type DepContext = TyCtxt<'tcx>;
75
76 #[inline]
77 fn dep_context(&self) -> &Self::DepContext {
78 &self.tcx
79 }
80}
81
82impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> {
83 #[inline]
84 fn jobserver_proxy(&self) -> &Proxy {
85 &self.tcx.jobserver_proxy
86 }
87
88 #[inline]
89 fn next_job_id(self) -> QueryJobId {
90 QueryJobId(
91 NonZero::new(
92 self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
93 )
94 .unwrap(),
95 )
96 }
97
98 #[inline]
99 fn current_query_job(self) -> Option<QueryJobId> {
100 tls::with_related_context(self.tcx, |icx| icx.query)
101 }
102
103 fn collect_active_jobs_from_all_queries(
114 self,
115 require_complete: bool,
116 ) -> Result<QueryMap<'tcx>, QueryMap<'tcx>> {
117 let mut jobs = QueryMap::default();
118 let mut complete = true;
119
120 for gather_fn in crate::PER_QUERY_GATHER_ACTIVE_JOBS_FNS.iter() {
121 if gather_fn(self.tcx, &mut jobs, require_complete).is_none() {
122 complete = false;
123 }
124 }
125
126 if complete { Ok(jobs) } else { Err(jobs) }
127 }
128
129 fn load_side_effect(
131 self,
132 prev_dep_node_index: SerializedDepNodeIndex,
133 ) -> Option<QuerySideEffect> {
134 self.tcx
135 .query_system
136 .on_disk_cache
137 .as_ref()
138 .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
139 }
140
141 #[inline(never)]
142 #[cold]
143 fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
144 if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() {
145 c.store_side_effect(dep_node_index, side_effect)
146 }
147 }
148
149 #[inline(always)]
152 fn start_query<R>(
153 self,
154 token: QueryJobId,
155 depth_limit: bool,
156 compute: impl FnOnce() -> R,
157 ) -> R {
158 tls::with_related_context(self.tcx, move |current_icx| {
162 if depth_limit
163 && !self.tcx.recursion_limit().value_within_limit(current_icx.query_depth)
164 {
165 self.depth_limit_error(token);
166 }
167
168 let new_icx = ImplicitCtxt {
170 tcx: self.tcx,
171 query: Some(token),
172 query_depth: current_icx.query_depth + depth_limit as usize,
173 task_deps: current_icx.task_deps,
174 };
175
176 tls::enter_context(&new_icx, compute)
178 })
179 }
180}
181
182pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
183 tcx.dep_graph.try_mark_green(QueryCtxt::new(tcx), dep_node).is_some()
184}
185
186pub(super) fn encode_all_query_results<'tcx>(
187 tcx: TyCtxt<'tcx>,
188 encoder: &mut CacheEncoder<'_, 'tcx>,
189 query_result_index: &mut EncodedDepNodeIndex,
190) {
191 for encode in super::ENCODE_QUERY_RESULTS.iter().copied().flatten() {
192 encode(tcx, encoder, query_result_index);
193 }
194}
195
196pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
197 if tcx.sess().opts.unstable_opts.incremental_verify_ich || truecfg!(debug_assertions) {
198 tcx.sess.time("query_key_hash_verify_all", || {
199 for verify in super::QUERY_KEY_HASH_VERIFY.iter() {
200 verify(tcx);
201 }
202 })
203 }
204}
205
206macro_rules! cycle_error_handling {
207 ([]) => {{
208 rustc_query_system::query::CycleErrorHandling::Error
209 }};
210 ([(cycle_fatal) $($rest:tt)*]) => {{
211 rustc_query_system::query::CycleErrorHandling::Fatal
212 }};
213 ([(cycle_stash) $($rest:tt)*]) => {{
214 rustc_query_system::query::CycleErrorHandling::Stash
215 }};
216 ([(cycle_delay_bug) $($rest:tt)*]) => {{
217 rustc_query_system::query::CycleErrorHandling::DelayBug
218 }};
219 ([$other:tt $($modifiers:tt)*]) => {
220 cycle_error_handling!([$($modifiers)*])
221 };
222}
223
224macro_rules! is_anon {
225 ([]) => {{
226 false
227 }};
228 ([(anon) $($rest:tt)*]) => {{
229 true
230 }};
231 ([$other:tt $($modifiers:tt)*]) => {
232 is_anon!([$($modifiers)*])
233 };
234}
235
236macro_rules! is_eval_always {
237 ([]) => {{
238 false
239 }};
240 ([(eval_always) $($rest:tt)*]) => {{
241 true
242 }};
243 ([$other:tt $($modifiers:tt)*]) => {
244 is_eval_always!([$($modifiers)*])
245 };
246}
247
248macro_rules! depth_limit {
249 ([]) => {{
250 false
251 }};
252 ([(depth_limit) $($rest:tt)*]) => {{
253 true
254 }};
255 ([$other:tt $($modifiers:tt)*]) => {
256 depth_limit!([$($modifiers)*])
257 };
258}
259
260macro_rules! feedable {
261 ([]) => {{
262 false
263 }};
264 ([(feedable) $($rest:tt)*]) => {{
265 true
266 }};
267 ([$other:tt $($modifiers:tt)*]) => {
268 feedable!([$($modifiers)*])
269 };
270}
271
272macro_rules! hash_result {
273 ([][$V:ty]) => {{
274 Some(|hcx, result| {
275 let result = ::rustc_middle::query::erase::restore_val::<$V>(*result);
276 ::rustc_query_system::dep_graph::hash_result(hcx, &result)
277 })
278 }};
279 ([(no_hash) $($rest:tt)*][$V:ty]) => {{
280 None
281 }};
282 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
283 hash_result!([$($modifiers)*][$($args)*])
284 };
285}
286
287macro_rules! call_provider {
288 ([][$tcx:expr, $name:ident, $key:expr]) => {{
289 ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
290 }};
291 ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
292 if let Some(key) = $key.as_local_key() {
293 ($tcx.query_system.fns.local_providers.$name)($tcx, key)
294 } else {
295 ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
296 }
297 }};
298 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
299 call_provider!([$($modifiers)*][$($args)*])
300 };
301}
302
303macro_rules! should_ever_cache_on_disk {
304 ([]$yes:tt $no:tt) => {{
305 $no
306 }};
307 ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{
308 $yes
309 }};
310 ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => {
311 should_ever_cache_on_disk!([$($modifiers)*]$yes $no)
312 };
313}
314
315fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>(
316 (tcx, key, kind, name, do_describe): (
317 TyCtxt<'tcx>,
318 K,
319 DepKind,
320 &'static str,
321 fn(TyCtxt<'tcx>, K) -> String,
322 ),
323) -> QueryStackFrameExtra {
324 let def_id = key.key_as_def_id();
325
326 let reduce_queries = with_reduced_queries();
329
330 let description = {
{
let _guard = ReducedQueriesGuard::new();
{
let _guard = ForcedImplGuard::new();
{
let _guard = NoTrimmedGuard::new();
{ let _guard = NoVisibleGuard::new(); do_describe(tcx, key) }
}
}
}
}ty::print::with_no_queries!(do_describe(tcx, key));
332 let description = if tcx.sess.verbose_internals() {
333 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} [{1:?}]", description, name))
})format!("{description} [{name:?}]")
334 } else {
335 description
336 };
337 let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries {
338 None
341 } else {
342 Some(key.default_span(tcx))
343 };
344
345 let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries {
346 None
348 } else {
349 def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
350 };
351 QueryStackFrameExtra::new(description, span, def_kind)
352}
353
354pub(crate) fn create_query_frame<
355 'tcx,
356 K: Copy + DynSend + DynSync + Key + for<'a> HashStable<StableHashingContext<'a>> + 'tcx,
357>(
358 tcx: TyCtxt<'tcx>,
359 do_describe: fn(TyCtxt<'tcx>, K) -> String,
360 key: K,
361 kind: DepKind,
362 name: &'static str,
363) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
364 let def_id = key.key_as_def_id();
365
366 let hash = tcx.with_stable_hashing_context(|mut hcx| {
367 let mut hasher = StableHasher::new();
368 kind.as_usize().hash_stable(&mut hcx, &mut hasher);
369 key.hash_stable(&mut hcx, &mut hasher);
370 hasher.finish::<Hash64>()
371 });
372 let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
373
374 let info =
375 QueryStackDeferred::new((tcx, key, kind, name, do_describe), mk_query_stack_frame_extra);
376
377 QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
378}
379
380pub(crate) fn encode_query_results<'a, 'tcx, Q>(
381 query: Q::Dispatcher,
382 qcx: QueryCtxt<'tcx>,
383 encoder: &mut CacheEncoder<'a, 'tcx>,
384 query_result_index: &mut EncodedDepNodeIndex,
385) where
386 Q: QueryDispatcherUnerased<'tcx>,
387 Q::UnerasedValue: Encodable<CacheEncoder<'a, 'tcx>>,
388{
389 let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name());
390
391 if !query.query_state(qcx).all_inactive() {
::core::panicking::panic("assertion failed: query.query_state(qcx).all_inactive()")
};assert!(query.query_state(qcx).all_inactive());
392 let cache = query.query_cache(qcx);
393 cache.iter(&mut |key, value, dep_node| {
394 if query.will_cache_on_disk_for_key(qcx.tcx, key) {
395 let dep_node = SerializedDepNodeIndex::new(dep_node.index());
396
397 query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
399
400 encoder.encode_tagged(dep_node, &Q::restore_val(*value));
403 }
404 });
405}
406
407pub(crate) fn query_key_hash_verify<'tcx>(
408 query: impl QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>,
409 qcx: QueryCtxt<'tcx>,
410) {
411 let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
412
413 let mut map = UnordMap::default();
414
415 let cache = query.query_cache(qcx);
416 cache.iter(&mut |key, _, _| {
417 let node = DepNode::construct(qcx.tcx, query.dep_kind(), key);
418 if let Some(other_key) = map.insert(node, *key) {
419 ::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!(
420 "query key:\n\
421 `{:?}`\n\
422 and key:\n\
423 `{:?}`\n\
424 mapped to the same dep node:\n\
425 {:?}",
426 key,
427 other_key,
428 node
429 );
430 }
431 });
432}
433
434fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
435where
436 Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>,
437{
438 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));
439
440 let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
441 {
::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)
442 });
443 if query.will_cache_on_disk_for_key(tcx, &key) {
444 let _ = query.execute_query(tcx, key);
445 }
446}
447
448pub(crate) fn loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
449 if let Some(cache) = tcx.query_system.on_disk_cache.as_ref() {
450 cache.loadable_from_disk(id)
451 } else {
452 false
453 }
454}
455
456pub(crate) fn try_load_from_disk<'tcx, V>(
457 tcx: TyCtxt<'tcx>,
458 prev_index: SerializedDepNodeIndex,
459 index: DepNodeIndex,
460) -> Option<V>
461where
462 V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
463{
464 let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
465
466 let prof_timer = tcx.prof.incr_cache_loading();
467
468 let value = tcx
472 .dep_graph
473 .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
474
475 prof_timer.finish_with_query_invocation_id(index.into());
476
477 value
478}
479
480fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
481where
482 Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>,
483{
484 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!(
498 dep_node.kind != dep_kinds::codegen_unit,
499 "calling force_from_dep_node() on dep_kinds::codegen_unit"
500 );
501
502 if let Some(key) = Q::Key::recover(tcx, &dep_node) {
503 force_query(query, QueryCtxt::new(tcx), key, dep_node);
504 true
505 } else {
506 false
507 }
508}
509
510pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
511 is_anon: bool,
512 is_eval_always: bool,
513) -> DepKindVTable<'tcx>
514where
515 Q: QueryDispatcherUnerased<'tcx>,
516{
517 let fingerprint_style = if is_anon {
518 FingerprintStyle::Opaque
519 } else {
520 <Q::Dispatcher as QueryDispatcher>::Key::fingerprint_style()
521 };
522
523 if is_anon || !fingerprint_style.reconstructible() {
524 return DepKindVTable {
525 is_anon,
526 is_eval_always,
527 fingerprint_style,
528 force_from_dep_node: None,
529 try_load_from_on_disk_cache: None,
530 name: Q::NAME,
531 };
532 }
533
534 DepKindVTable {
535 is_anon,
536 is_eval_always,
537 fingerprint_style,
538 force_from_dep_node: Some(|tcx, dep_node, _| {
539 force_from_dep_node(Q::query_dispatcher(tcx), tcx, dep_node)
540 }),
541 try_load_from_on_disk_cache: Some(|tcx, dep_node| {
542 try_load_from_on_disk_cache(Q::query_dispatcher(tcx), tcx, dep_node)
543 }),
544 name: Q::NAME,
545 }
546}
547
548macro_rules! item_if_cached {
549 ([] $tokens:tt) => {};
550 ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
551 $($tokens)*
552 };
553 ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
554 item_if_cached! { [$($modifiers)*] $tokens }
555 };
556}
557
558macro_rules! expand_if_cached {
559 ([], $tokens:expr) => {{
560 None
561 }};
562 ([(cache) $($rest:tt)*], $tokens:expr) => {{
563 Some($tokens)
564 }};
565 ([$other:tt $($modifiers:tt)*], $tokens:expr) => {
566 expand_if_cached!([$($modifiers)*], $tokens)
567 };
568}
569
570#[inline(never)]
573pub(crate) fn __rust_begin_short_backtrace<F, T>(f: F) -> T
574where
575 F: FnOnce() -> T,
576{
577 let result = f();
578 std::hint::black_box(());
579 result
580}
581
582macro_rules! define_queries {
585 (
586 $(
587 $(#[$attr:meta])*
588 [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,
589 )*
590 ) => {
591
592 pub(crate) mod query_impl { $(pub(crate) mod $name {
593 use super::super::*;
594 use std::marker::PhantomData;
595 use ::rustc_middle::query::erase::{self, Erased};
596
597 pub(crate) mod get_query_incr {
598 use super::*;
599
600 #[inline(never)]
603 pub(crate) fn __rust_end_short_backtrace<'tcx>(
604 tcx: TyCtxt<'tcx>,
605 span: Span,
606 key: queries::$name::Key<'tcx>,
607 mode: QueryMode,
608 ) -> Option<Erased<queries::$name::Value<'tcx>>> {
609 #[cfg(debug_assertions)]
610 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
611 get_query_incr(
612 QueryType::query_dispatcher(tcx),
613 QueryCtxt::new(tcx),
614 span,
615 key,
616 mode
617 )
618 }
619 }
620
621 pub(crate) mod get_query_non_incr {
622 use super::*;
623
624 #[inline(never)]
625 pub(crate) fn __rust_end_short_backtrace<'tcx>(
626 tcx: TyCtxt<'tcx>,
627 span: Span,
628 key: queries::$name::Key<'tcx>,
629 __mode: QueryMode,
630 ) -> Option<Erased<queries::$name::Value<'tcx>>> {
631 Some(get_query_non_incr(
632 QueryType::query_dispatcher(tcx),
633 QueryCtxt::new(tcx),
634 span,
635 key,
636 ))
637 }
638 }
639
640 pub(crate) fn make_query_vtable<'tcx>()
641 -> QueryVTable<'tcx, queries::$name::Storage<'tcx>>
642 {
643 QueryVTable {
644 name: stringify!($name),
645 eval_always: is_eval_always!([$($modifiers)*]),
646 dep_kind: dep_graph::dep_kinds::$name,
647 cycle_error_handling: cycle_error_handling!([$($modifiers)*]),
648 query_state: std::mem::offset_of!(QueryStates<'tcx>, $name),
649 query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name),
650 will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] {
651 Some(::rustc_middle::query::cached::$name)
652 } {
653 None
654 }),
655 execute_query: |tcx, key| erase::erase_val(tcx.$name(key)),
656 compute: |tcx, key| {
657 #[cfg(debug_assertions)]
658 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
659 __rust_begin_short_backtrace(||
660 queries::$name::provided_to_erased(
661 tcx,
662 {
663 let ret = call_provider!([$($modifiers)*][tcx, $name, key]);
664 rustc_middle::ty::print::with_reduced_queries!({
665 tracing::trace!(?ret);
666 });
667 ret
668 }
669 )
670 )
671 },
672 try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] {
673 Some(|tcx, key, prev_index, index| {
674 if !::rustc_middle::query::cached::$name(tcx, key) {
676 return None;
677 }
678
679 let value: queries::$name::ProvidedValue<'tcx> =
680 $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?;
681
682 Some(queries::$name::provided_to_erased(tcx, value))
684 })
685 } {
686 None
687 }),
688 is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] {
689 Some(|tcx, key, index| -> bool {
690 ::rustc_middle::query::cached::$name(tcx, key) &&
691 $crate::plumbing::loadable_from_disk(tcx, index)
692 })
693 } {
694 None
695 }),
696 value_from_cycle_error: |tcx, cycle, guar| {
697 let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar);
698 erase::erase_val(result)
699 },
700 hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
701 format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
702 }
703 }
704
705 #[derive(Copy, Clone, Default)]
706 pub(crate) struct QueryType<'tcx> {
707 data: PhantomData<&'tcx ()>
708 }
709
710 const FLAGS: QueryFlags = QueryFlags {
711 is_anon: is_anon!([$($modifiers)*]),
712 is_depth_limit: depth_limit!([$($modifiers)*]),
713 is_feedable: feedable!([$($modifiers)*]),
714 };
715
716 impl<'tcx> QueryDispatcherUnerased<'tcx> for QueryType<'tcx> {
717 type UnerasedValue = queries::$name::Value<'tcx>;
718 type Dispatcher = SemiDynamicQueryDispatcher<
719 'tcx,
720 queries::$name::Storage<'tcx>,
721 FLAGS,
722 >;
723
724 const NAME: &'static &'static str = &stringify!($name);
725
726 #[inline(always)]
727 fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher {
728 SemiDynamicQueryDispatcher {
729 vtable: &tcx.query_system.query_vtables.$name,
730 }
731 }
732
733 #[inline(always)]
734 fn restore_val(value: <Self::Dispatcher as QueryDispatcher<'tcx>>::Value) -> Self::UnerasedValue {
735 erase::restore_val::<queries::$name::Value<'tcx>>(value)
736 }
737 }
738
739 pub(crate) fn gather_active_jobs<'tcx>(
743 tcx: TyCtxt<'tcx>,
744 qmap: &mut QueryMap<'tcx>,
745 require_complete: bool,
746 ) -> Option<()> {
747 let make_frame = |tcx, key| {
748 let kind = rustc_middle::dep_graph::dep_kinds::$name;
749 let name = stringify!($name);
750 $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
751 };
752
753 let res = tcx.query_system.states.$name.gather_active_jobs_inner(
755 tcx,
756 make_frame,
757 qmap,
758 require_complete,
759 );
760
761 if res.is_none() {
765 tracing::warn!(
766 "Failed to collect active jobs for query with name `{}`!",
767 stringify!($name)
768 );
769 }
770 res
771 }
772
773 pub(crate) fn alloc_self_profile_query_strings<'tcx>(
774 tcx: TyCtxt<'tcx>,
775 string_cache: &mut QueryKeyStringCache
776 ) {
777 $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
778 tcx,
779 stringify!($name),
780 &tcx.query_system.caches.$name,
781 string_cache,
782 )
783 }
784
785 item_if_cached! { [$($modifiers)*] {
786 pub(crate) fn encode_query_results<'tcx>(
787 tcx: TyCtxt<'tcx>,
788 encoder: &mut CacheEncoder<'_, 'tcx>,
789 query_result_index: &mut EncodedDepNodeIndex
790 ) {
791 $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
792 query_impl::$name::QueryType::query_dispatcher(tcx),
793 QueryCtxt::new(tcx),
794 encoder,
795 query_result_index,
796 )
797 }
798 }}
799
800 pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) {
801 $crate::plumbing::query_key_hash_verify(
802 query_impl::$name::QueryType::query_dispatcher(tcx),
803 QueryCtxt::new(tcx),
804 )
805 }
806 })*}
807
808 pub(crate) fn engine(incremental: bool) -> QueryEngine {
809 if incremental {
810 QueryEngine {
811 $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
812 }
813 } else {
814 QueryEngine {
815 $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
816 }
817 }
818 }
819
820 pub fn make_query_vtables<'tcx>() -> ::rustc_middle::query::PerQueryVTables<'tcx> {
821 ::rustc_middle::query::PerQueryVTables {
822 $(
823 $name: query_impl::$name::make_query_vtable(),
824 )*
825 }
826 }
827
828 const PER_QUERY_GATHER_ACTIVE_JOBS_FNS: &[
837 for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, require_complete: bool) -> Option<()>
838 ] = &[
839 $(query_impl::$name::gather_active_jobs),*
840 ];
841
842 const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
843 for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
844 ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
845
846 const ENCODE_QUERY_RESULTS: &[
847 Option<for<'tcx> fn(
848 TyCtxt<'tcx>,
849 &mut CacheEncoder<'_, 'tcx>,
850 &mut EncodedDepNodeIndex)
851 >
852 ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
853
854 const QUERY_KEY_HASH_VERIFY: &[
855 for<'tcx> fn(TyCtxt<'tcx>)
856 ] = &[$(query_impl::$name::query_key_hash_verify),*];
857
858 #[expect(non_snake_case)]
863 mod _dep_kind_vtable_ctors {
864 use super::*;
865 use rustc_middle::bug;
866 use rustc_query_system::dep_graph::FingerprintStyle;
867
868 pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> {
870 DepKindVTable {
871 is_anon: false,
872 is_eval_always: false,
873 fingerprint_style: FingerprintStyle::Unit,
874 force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
875 try_load_from_on_disk_cache: None,
876 name: &"Null",
877 }
878 }
879
880 pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> {
882 DepKindVTable {
883 is_anon: false,
884 is_eval_always: false,
885 fingerprint_style: FingerprintStyle::Unit,
886 force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
887 try_load_from_on_disk_cache: None,
888 name: &"Red",
889 }
890 }
891
892 pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> {
893 DepKindVTable {
894 is_anon: false,
895 is_eval_always: false,
896 fingerprint_style: FingerprintStyle::Unit,
897 force_from_dep_node: Some(|tcx, _, prev_index| {
898 tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
899 true
900 }),
901 try_load_from_on_disk_cache: None,
902 name: &"SideEffect",
903 }
904 }
905
906 pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> {
907 DepKindVTable {
908 is_anon: true,
909 is_eval_always: false,
910 fingerprint_style: FingerprintStyle::Opaque,
911 force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")),
912 try_load_from_on_disk_cache: None,
913 name: &"AnonZeroDeps",
914 }
915 }
916
917 pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> {
918 DepKindVTable {
919 is_anon: true,
920 is_eval_always: false,
921 fingerprint_style: FingerprintStyle::Unit,
922 force_from_dep_node: None,
923 try_load_from_on_disk_cache: None,
924 name: &"TraitSelect",
925 }
926 }
927
928 pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> {
929 DepKindVTable {
930 is_anon: false,
931 is_eval_always: false,
932 fingerprint_style: FingerprintStyle::Opaque,
933 force_from_dep_node: None,
934 try_load_from_on_disk_cache: None,
935 name: &"CompileCodegenUnit",
936 }
937 }
938
939 pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> {
940 DepKindVTable {
941 is_anon: false,
942 is_eval_always: false,
943 fingerprint_style: FingerprintStyle::Opaque,
944 force_from_dep_node: None,
945 try_load_from_on_disk_cache: None,
946 name: &"CompileMonoItem",
947 }
948 }
949
950 pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> {
951 DepKindVTable {
952 is_anon: false,
953 is_eval_always: false,
954 fingerprint_style: FingerprintStyle::Unit,
955 force_from_dep_node: None,
956 try_load_from_on_disk_cache: None,
957 name: &"Metadata",
958 }
959 }
960
961 $(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> {
962 use $crate::query_impl::$name::QueryType;
963 $crate::plumbing::make_dep_kind_vtable_for_query::<QueryType<'tcx>>(
964 is_anon!([$($modifiers)*]),
965 is_eval_always!([$($modifiers)*]),
966 )
967 })*
968 }
969
970 pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] {
971 arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors))
972 }
973 }
974}