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