1 //! The implementation of the query system itself. This defines the macros that
2 //! generate the actual methods on tcx which find and execute the provider,
3 //! manage the caches, and so forth.
4
5 use crate::rustc_middle::dep_graph::DepContext;
6 use crate::rustc_middle::ty::TyEncoder;
7 use crate::QueryConfigRestored;
8 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
9 use rustc_data_structures::sync::Lock;
10 use rustc_errors::Diagnostic;
11 use rustc_index::Idx;
12 use rustc_middle::dep_graph::{
13 self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
14 };
15 use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
16 use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
17 use rustc_middle::query::Key;
18 use rustc_middle::ty::tls::{self, ImplicitCtxt};
19 use rustc_middle::ty::{self, print::with_no_queries, TyCtxt};
20 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
21 use rustc_query_system::ich::StableHashingContext;
22 use rustc_query_system::query::{
23 force_query, QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects,
24 QueryStackFrame,
25 };
26 use rustc_query_system::{LayoutOfDepth, QueryOverflow};
27 use rustc_serialize::Decodable;
28 use rustc_serialize::Encodable;
29 use rustc_session::Limit;
30 use rustc_span::def_id::LOCAL_CRATE;
31 use std::num::NonZeroU64;
32 use thin_vec::ThinVec;
33
34 #[derive(Copy, Clone)]
35 pub struct QueryCtxt<'tcx> {
36 pub tcx: TyCtxt<'tcx>,
37 }
38
39 impl<'tcx> QueryCtxt<'tcx> {
40 #[inline]
new(tcx: TyCtxt<'tcx>) -> Self41 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
42 QueryCtxt { tcx }
43 }
44 }
45
46 impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> {
47 type Target = TyCtxt<'tcx>;
48
49 #[inline]
deref(&self) -> &Self::Target50 fn deref(&self) -> &Self::Target {
51 &self.tcx
52 }
53 }
54
55 impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
56 type DepKind = rustc_middle::dep_graph::DepKind;
57 type DepContext = TyCtxt<'tcx>;
58
59 #[inline]
dep_context(&self) -> &Self::DepContext60 fn dep_context(&self) -> &Self::DepContext {
61 &self.tcx
62 }
63 }
64
65 impl QueryContext for QueryCtxt<'_> {
66 #[inline]
next_job_id(self) -> QueryJobId67 fn next_job_id(self) -> QueryJobId {
68 QueryJobId(
69 NonZeroU64::new(
70 self.query_system.jobs.fetch_add(1, rustc_data_structures::sync::Ordering::Relaxed),
71 )
72 .unwrap(),
73 )
74 }
75
76 #[inline]
current_query_job(self) -> Option<QueryJobId>77 fn current_query_job(self) -> Option<QueryJobId> {
78 tls::with_related_context(self.tcx, |icx| icx.query)
79 }
80
try_collect_active_jobs(self) -> Option<QueryMap<DepKind>>81 fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
82 let mut jobs = QueryMap::default();
83
84 for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
85 collect(self.tcx, &mut jobs);
86 }
87
88 Some(jobs)
89 }
90
91 // Interactions with on_disk_cache
load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects92 fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
93 self.query_system
94 .on_disk_cache
95 .as_ref()
96 .map(|c| c.load_side_effects(self.tcx, prev_dep_node_index))
97 .unwrap_or_default()
98 }
99
100 #[inline(never)]
101 #[cold]
store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects)102 fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
103 if let Some(c) = self.query_system.on_disk_cache.as_ref() {
104 c.store_side_effects(dep_node_index, side_effects)
105 }
106 }
107
108 #[inline(never)]
109 #[cold]
store_side_effects_for_anon_node( self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects, )110 fn store_side_effects_for_anon_node(
111 self,
112 dep_node_index: DepNodeIndex,
113 side_effects: QuerySideEffects,
114 ) {
115 if let Some(c) = self.query_system.on_disk_cache.as_ref() {
116 c.store_side_effects_for_anon_node(dep_node_index, side_effects)
117 }
118 }
119
120 /// Executes a job by changing the `ImplicitCtxt` to point to the
121 /// new query job while it executes. It returns the diagnostics
122 /// captured during execution and the actual result.
123 #[inline(always)]
start_query<R>( self, token: QueryJobId, depth_limit: bool, diagnostics: Option<&Lock<ThinVec<Diagnostic>>>, compute: impl FnOnce() -> R, ) -> R124 fn start_query<R>(
125 self,
126 token: QueryJobId,
127 depth_limit: bool,
128 diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
129 compute: impl FnOnce() -> R,
130 ) -> R {
131 // The `TyCtxt` stored in TLS has the same global interner lifetime
132 // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
133 // when accessing the `ImplicitCtxt`.
134 tls::with_related_context(self.tcx, move |current_icx| {
135 if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
136 self.depth_limit_error(token);
137 }
138
139 // Update the `ImplicitCtxt` to point to our new query job.
140 let new_icx = ImplicitCtxt {
141 tcx: self.tcx,
142 query: Some(token),
143 diagnostics,
144 query_depth: current_icx.query_depth + depth_limit as usize,
145 task_deps: current_icx.task_deps,
146 };
147
148 // Use the `ImplicitCtxt` while we execute the query.
149 tls::enter_context(&new_icx, compute)
150 })
151 }
152
depth_limit_error(self, job: QueryJobId)153 fn depth_limit_error(self, job: QueryJobId) {
154 let mut span = None;
155 let mut layout_of_depth = None;
156 if let Some(map) = self.try_collect_active_jobs() {
157 if let Some((info, depth)) = job.try_find_layout_root(map) {
158 span = Some(info.job.span);
159 layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth });
160 }
161 }
162
163 let suggested_limit = match self.recursion_limit() {
164 Limit(0) => Limit(2),
165 limit => limit * 2,
166 };
167
168 self.sess.emit_fatal(QueryOverflow {
169 span,
170 layout_of_depth,
171 suggested_limit,
172 crate_name: self.crate_name(LOCAL_CRATE),
173 });
174 }
175 }
176
try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool177 pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
178 tcx.dep_graph.try_mark_green(QueryCtxt::new(tcx), dep_node).is_some()
179 }
180
encode_all_query_results<'tcx>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, )181 pub(super) fn encode_all_query_results<'tcx>(
182 tcx: TyCtxt<'tcx>,
183 encoder: &mut CacheEncoder<'_, 'tcx>,
184 query_result_index: &mut EncodedDepNodeIndex,
185 ) {
186 for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) {
187 encode(tcx, encoder, query_result_index);
188 }
189 }
190
191 macro_rules! handle_cycle_error {
192 ([]) => {{
193 rustc_query_system::HandleCycleError::Error
194 }};
195 ([(fatal_cycle) $($rest:tt)*]) => {{
196 rustc_query_system::HandleCycleError::Fatal
197 }};
198 ([(cycle_delay_bug) $($rest:tt)*]) => {{
199 rustc_query_system::HandleCycleError::DelayBug
200 }};
201 ([$other:tt $($modifiers:tt)*]) => {
202 handle_cycle_error!([$($modifiers)*])
203 };
204 }
205
206 macro_rules! is_anon {
207 ([]) => {{
208 false
209 }};
210 ([(anon) $($rest:tt)*]) => {{
211 true
212 }};
213 ([$other:tt $($modifiers:tt)*]) => {
214 is_anon!([$($modifiers)*])
215 };
216 }
217
218 macro_rules! is_eval_always {
219 ([]) => {{
220 false
221 }};
222 ([(eval_always) $($rest:tt)*]) => {{
223 true
224 }};
225 ([$other:tt $($modifiers:tt)*]) => {
226 is_eval_always!([$($modifiers)*])
227 };
228 }
229
230 macro_rules! depth_limit {
231 ([]) => {{
232 false
233 }};
234 ([(depth_limit) $($rest:tt)*]) => {{
235 true
236 }};
237 ([$other:tt $($modifiers:tt)*]) => {
238 depth_limit!([$($modifiers)*])
239 };
240 }
241
242 macro_rules! feedable {
243 ([]) => {{
244 false
245 }};
246 ([(feedable) $($rest:tt)*]) => {{
247 true
248 }};
249 ([$other:tt $($modifiers:tt)*]) => {
250 feedable!([$($modifiers)*])
251 };
252 }
253
254 macro_rules! hash_result {
255 ([][$V:ty]) => {{
256 Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result)))
257 }};
258 ([(no_hash) $($rest:tt)*][$V:ty]) => {{
259 None
260 }};
261 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
262 hash_result!([$($modifiers)*][$($args)*])
263 };
264 }
265
266 macro_rules! call_provider {
267 ([][$tcx:expr, $name:ident, $key:expr]) => {{
268 ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
269 }};
270 ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
271 if let Some(key) = $key.as_local_key() {
272 ($tcx.query_system.fns.local_providers.$name)($tcx, key)
273 } else {
274 ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
275 }
276 }};
277 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
278 call_provider!([$($modifiers)*][$($args)*])
279 };
280 }
281
282 macro_rules! should_ever_cache_on_disk {
283 ([]$yes:tt $no:tt) => {{
284 $no
285 }};
286 ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{
287 $yes
288 }};
289 ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => {
290 should_ever_cache_on_disk!([$($modifiers)*]$yes $no)
291 };
292 }
293
create_query_frame< 'tcx, K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>, >( tcx: TyCtxt<'tcx>, do_describe: fn(TyCtxt<'tcx>, K) -> String, key: K, kind: DepKind, name: &'static str, ) -> QueryStackFrame<DepKind>294 pub(crate) fn create_query_frame<
295 'tcx,
296 K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
297 >(
298 tcx: TyCtxt<'tcx>,
299 do_describe: fn(TyCtxt<'tcx>, K) -> String,
300 key: K,
301 kind: DepKind,
302 name: &'static str,
303 ) -> QueryStackFrame<DepKind> {
304 // Avoid calling queries while formatting the description
305 let description = ty::print::with_no_queries!(
306 // Disable visible paths printing for performance reasons.
307 // Showing visible path instead of any path is not that important in production.
308 ty::print::with_no_visible_paths!(
309 // Force filename-line mode to avoid invoking `type_of` query.
310 ty::print::with_forced_impl_filename_line!(do_describe(tcx, key))
311 )
312 );
313 let description =
314 if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description };
315 let span = if kind == dep_graph::DepKind::def_span || with_no_queries() {
316 // The `def_span` query is used to calculate `default_span`,
317 // so exit to avoid infinite recursion.
318 None
319 } else {
320 Some(key.default_span(tcx))
321 };
322 let def_id = key.key_as_def_id();
323 let def_kind = if kind == dep_graph::DepKind::opt_def_kind || with_no_queries() {
324 // Try to avoid infinite recursion.
325 None
326 } else {
327 def_id.and_then(|def_id| def_id.as_local()).and_then(|def_id| tcx.opt_def_kind(def_id))
328 };
329 let hash = || {
330 tcx.with_stable_hashing_context(|mut hcx| {
331 let mut hasher = StableHasher::new();
332 std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
333 key.hash_stable(&mut hcx, &mut hasher);
334 hasher.finish::<Hash64>()
335 })
336 };
337 let ty_adt_id = key.ty_adt_id();
338
339 QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash)
340 }
341
encode_query_results<'a, 'tcx, Q>( query: Q::Config, qcx: QueryCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ) where Q: super::QueryConfigRestored<'tcx>, Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,342 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
343 query: Q::Config,
344 qcx: QueryCtxt<'tcx>,
345 encoder: &mut CacheEncoder<'a, 'tcx>,
346 query_result_index: &mut EncodedDepNodeIndex,
347 ) where
348 Q: super::QueryConfigRestored<'tcx>,
349 Q::RestoredValue: Encodable<CacheEncoder<'a, 'tcx>>,
350 {
351 let _timer =
352 qcx.profiler().verbose_generic_activity_with_arg("encode_query_results_for", query.name());
353
354 assert!(query.query_state(qcx).all_inactive());
355 let cache = query.query_cache(qcx);
356 cache.iter(&mut |key, value, dep_node| {
357 if query.cache_on_disk(qcx.tcx, &key) {
358 let dep_node = SerializedDepNodeIndex::new(dep_node.index());
359
360 // Record position of the cache entry.
361 query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
362
363 // Encode the type check tables with the `SerializedDepNodeIndex`
364 // as tag.
365 encoder.encode_tagged(dep_node, &Q::restore(*value));
366 }
367 });
368 }
369
try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where Q: QueryConfig<QueryCtxt<'tcx>>,370 fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
371 where
372 Q: QueryConfig<QueryCtxt<'tcx>>,
373 {
374 debug_assert!(tcx.dep_graph.is_green(&dep_node));
375
376 let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
377 panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
378 });
379 if query.cache_on_disk(tcx, &key) {
380 let _ = query.execute_query(tcx, key);
381 }
382 }
383
loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool384 pub(crate) fn loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
385 if let Some(cache) = tcx.query_system.on_disk_cache.as_ref() {
386 cache.loadable_from_disk(id)
387 } else {
388 false
389 }
390 }
391
try_load_from_disk<'tcx, V>( tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option<V> where V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,392 pub(crate) fn try_load_from_disk<'tcx, V>(
393 tcx: TyCtxt<'tcx>,
394 prev_index: SerializedDepNodeIndex,
395 index: DepNodeIndex,
396 ) -> Option<V>
397 where
398 V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
399 {
400 let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
401
402 let prof_timer = tcx.prof.incr_cache_loading();
403
404 // The call to `with_query_deserialization` enforces that no new `DepNodes`
405 // are created during deserialization. See the docs of that method for more
406 // details.
407 let value = tcx
408 .dep_graph
409 .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
410
411 prof_timer.finish_with_query_invocation_id(index.into());
412
413 value
414 }
415
force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where Q: QueryConfig<QueryCtxt<'tcx>>,416 fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
417 where
418 Q: QueryConfig<QueryCtxt<'tcx>>,
419 {
420 // We must avoid ever having to call `force_from_dep_node()` for a
421 // `DepNode::codegen_unit`:
422 // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
423 // would always end up having to evaluate the first caller of the
424 // `codegen_unit` query that *is* reconstructible. This might very well be
425 // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
426 // to re-trigger calling the `codegen_unit` query with the right key. At
427 // that point we would already have re-done all the work we are trying to
428 // avoid doing in the first place.
429 // The solution is simple: Just explicitly call the `codegen_unit` query for
430 // each CGU, right after partitioning. This way `try_mark_green` will always
431 // hit the cache instead of having to go through `force_from_dep_node`.
432 // This assertion makes sure, we actually keep applying the solution above.
433 debug_assert!(
434 dep_node.kind != DepKind::codegen_unit,
435 "calling force_from_dep_node() on DepKind::codegen_unit"
436 );
437
438 if let Some(key) = Q::Key::recover(tcx, &dep_node) {
439 #[cfg(debug_assertions)]
440 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
441 force_query(query, QueryCtxt::new(tcx), key, dep_node);
442 true
443 } else {
444 false
445 }
446 }
447
query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx> where Q: QueryConfigRestored<'tcx>,448 pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
449 where
450 Q: QueryConfigRestored<'tcx>,
451 {
452 let fingerprint_style = <Q::Config as QueryConfig<QueryCtxt<'tcx>>>::Key::fingerprint_style();
453
454 if is_anon || !fingerprint_style.reconstructible() {
455 return DepKindStruct {
456 is_anon,
457 is_eval_always,
458 fingerprint_style,
459 force_from_dep_node: None,
460 try_load_from_on_disk_cache: None,
461 };
462 }
463
464 DepKindStruct {
465 is_anon,
466 is_eval_always,
467 fingerprint_style,
468 force_from_dep_node: Some(|tcx, dep_node| {
469 force_from_dep_node(Q::config(tcx), tcx, dep_node)
470 }),
471 try_load_from_on_disk_cache: Some(|tcx, dep_node| {
472 try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node)
473 }),
474 }
475 }
476
477 macro_rules! item_if_cached {
478 ([] $tokens:tt) => {};
479 ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
480 $($tokens)*
481 };
482 ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
483 item_if_cached! { [$($modifiers)*] $tokens }
484 };
485 }
486
487 macro_rules! expand_if_cached {
488 ([], $tokens:expr) => {{
489 None
490 }};
491 ([(cache) $($rest:tt)*], $tokens:expr) => {{
492 Some($tokens)
493 }};
494 ([$other:tt $($modifiers:tt)*], $tokens:expr) => {
495 expand_if_cached!([$($modifiers)*], $tokens)
496 };
497 }
498
499 /// Don't show the backtrace for query system by default
500 /// use `RUST_BACKTRACE=full` to show all the backtraces
501 #[inline(never)]
__rust_begin_short_backtrace<F, T>(f: F) -> T where F: FnOnce() -> T,502 pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
503 where
504 F: FnOnce() -> T,
505 {
506 let result = f();
507 std::hint::black_box(());
508 result
509 }
510
511 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
512 // invoked by `rustc_query_append`.
513 macro_rules! define_queries {
514 (
515 $($(#[$attr:meta])*
516 [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
517
518 pub(crate) mod query_impl { $(pub mod $name {
519 use super::super::*;
520 use std::marker::PhantomData;
521
522 pub mod get_query_incr {
523 use super::*;
524
525 // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
526 // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
527 #[inline(never)]
528 pub fn __rust_end_short_backtrace<'tcx>(
529 tcx: TyCtxt<'tcx>,
530 span: Span,
531 key: queries::$name::Key<'tcx>,
532 mode: QueryMode,
533 ) -> Option<Erase<queries::$name::Value<'tcx>>> {
534 #[cfg(debug_assertions)]
535 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
536 get_query_incr(
537 QueryType::config(tcx),
538 QueryCtxt::new(tcx),
539 span,
540 key,
541 mode
542 )
543 }
544 }
545
546 pub mod get_query_non_incr {
547 use super::*;
548
549 #[inline(never)]
550 pub fn __rust_end_short_backtrace<'tcx>(
551 tcx: TyCtxt<'tcx>,
552 span: Span,
553 key: queries::$name::Key<'tcx>,
554 __mode: QueryMode,
555 ) -> Option<Erase<queries::$name::Value<'tcx>>> {
556 Some(get_query_non_incr(
557 QueryType::config(tcx),
558 QueryCtxt::new(tcx),
559 span,
560 key,
561 ))
562 }
563 }
564
565 pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> {
566 DynamicQuery {
567 name: stringify!($name),
568 eval_always: is_eval_always!([$($modifiers)*]),
569 dep_kind: dep_graph::DepKind::$name,
570 handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
571 query_state: offset_of!(QueryStates<'tcx> => $name),
572 query_cache: offset_of!(QueryCaches<'tcx> => $name),
573 cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
574 execute_query: |tcx, key| erase(tcx.$name(key)),
575 compute: |tcx, key| {
576 #[cfg(debug_assertions)]
577 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
578 __rust_begin_short_backtrace(||
579 queries::$name::provided_to_erased(
580 tcx,
581 {
582 let ret = call_provider!([$($modifiers)*][tcx, $name, key]);
583 tracing::trace!(?ret);
584 ret
585 }
586 )
587 )
588 },
589 can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
590 try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
591 |tcx, key, prev_index, index| {
592 if ::rustc_middle::query::cached::$name(tcx, key) {
593 let value = $crate::plumbing::try_load_from_disk::<
594 queries::$name::ProvidedValue<'tcx>
595 >(
596 tcx,
597 prev_index,
598 index,
599 );
600 value.map(|value| queries::$name::provided_to_erased(tcx, value))
601 } else {
602 None
603 }
604 }
605 } {
606 |_tcx, _key, _prev_index, _index| None
607 }),
608 value_from_cycle_error: |tcx, cycle| {
609 let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle);
610 erase(result)
611 },
612 loadable_from_disk: |_tcx, _key, _index| {
613 should_ever_cache_on_disk!([$($modifiers)*] {
614 ::rustc_middle::query::cached::$name(_tcx, _key) &&
615 $crate::plumbing::loadable_from_disk(_tcx, _index)
616 } {
617 false
618 })
619 },
620 hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
621 format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
622 }
623 }
624
625 #[derive(Copy, Clone, Default)]
626 pub struct QueryType<'tcx> {
627 data: PhantomData<&'tcx ()>
628 }
629
630 impl<'tcx> QueryConfigRestored<'tcx> for QueryType<'tcx> {
631 type RestoredValue = queries::$name::Value<'tcx>;
632 type Config = DynamicConfig<
633 'tcx,
634 queries::$name::Storage<'tcx>,
635 { is_anon!([$($modifiers)*]) },
636 { depth_limit!([$($modifiers)*]) },
637 { feedable!([$($modifiers)*]) },
638 >;
639
640 #[inline(always)]
641 fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
642 DynamicConfig {
643 dynamic: &tcx.query_system.dynamic_queries.$name,
644 }
645 }
646
647 #[inline(always)]
648 fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
649 restore::<queries::$name::Value<'tcx>>(value)
650 }
651 }
652
653 pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap<DepKind>) {
654 let make_query = |tcx, key| {
655 let kind = rustc_middle::dep_graph::DepKind::$name;
656 let name = stringify!($name);
657 $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
658 };
659 tcx.query_system.states.$name.try_collect_active_jobs(
660 tcx,
661 make_query,
662 qmap,
663 ).unwrap();
664 }
665
666 pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) {
667 $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
668 tcx,
669 stringify!($name),
670 &tcx.query_system.caches.$name,
671 string_cache,
672 )
673 }
674
675 item_if_cached! { [$($modifiers)*] {
676 pub fn encode_query_results<'tcx>(
677 tcx: TyCtxt<'tcx>,
678 encoder: &mut CacheEncoder<'_, 'tcx>,
679 query_result_index: &mut EncodedDepNodeIndex
680 ) {
681 $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
682 query_impl::$name::QueryType::config(tcx),
683 QueryCtxt::new(tcx),
684 encoder,
685 query_result_index,
686 )
687 }
688 }}
689 })*}
690
691 pub(crate) fn engine(incremental: bool) -> QueryEngine {
692 if incremental {
693 QueryEngine {
694 $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
695 }
696 } else {
697 QueryEngine {
698 $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
699 }
700 }
701 }
702
703 pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
704 DynamicQueries {
705 $(
706 $name: query_impl::$name::dynamic_query(),
707 )*
708 }
709 }
710
711 // These arrays are used for iteration and can't be indexed by `DepKind`.
712
713 const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>)] =
714 &[$(query_impl::$name::try_collect_active_jobs),*];
715
716 const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
717 for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
718 ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
719
720 const ENCODE_QUERY_RESULTS: &[
721 Option<for<'tcx> fn(
722 TyCtxt<'tcx>,
723 &mut CacheEncoder<'_, 'tcx>,
724 &mut EncodedDepNodeIndex)
725 >
726 ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
727
728 #[allow(nonstandard_style)]
729 mod query_callbacks {
730 use super::*;
731 use rustc_query_system::dep_graph::FingerprintStyle;
732
733 // We use this for most things when incr. comp. is turned off.
734 pub fn Null<'tcx>() -> DepKindStruct<'tcx> {
735 DepKindStruct {
736 is_anon: false,
737 is_eval_always: false,
738 fingerprint_style: FingerprintStyle::Unit,
739 force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
740 try_load_from_on_disk_cache: None,
741 }
742 }
743
744 // We use this for the forever-red node.
745 pub fn Red<'tcx>() -> DepKindStruct<'tcx> {
746 DepKindStruct {
747 is_anon: false,
748 is_eval_always: false,
749 fingerprint_style: FingerprintStyle::Unit,
750 force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
751 try_load_from_on_disk_cache: None,
752 }
753 }
754
755 pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
756 DepKindStruct {
757 is_anon: true,
758 is_eval_always: false,
759 fingerprint_style: FingerprintStyle::Unit,
760 force_from_dep_node: None,
761 try_load_from_on_disk_cache: None,
762 }
763 }
764
765 pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
766 DepKindStruct {
767 is_anon: false,
768 is_eval_always: false,
769 fingerprint_style: FingerprintStyle::Opaque,
770 force_from_dep_node: None,
771 try_load_from_on_disk_cache: None,
772 }
773 }
774
775 pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
776 DepKindStruct {
777 is_anon: false,
778 is_eval_always: false,
779 fingerprint_style: FingerprintStyle::Opaque,
780 force_from_dep_node: None,
781 try_load_from_on_disk_cache: None,
782 }
783 }
784
785 $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
786 $crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
787 is_anon!([$($modifiers)*]),
788 is_eval_always!([$($modifiers)*]),
789 )
790 })*
791 }
792
793 pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
794 arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
795 }
796 }
797 }
798