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