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