1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The implementation of the query system itself. Defines the macros
12 //! that generate the actual methods on tcx which find and execute the
13 //! provider, manage the caches, and so forth.
15 use dep_graph
::{DepNodeIndex, DepNode, DepKind, DepNodeColor}
;
16 use errors
::DiagnosticBuilder
;
18 use errors
::Diagnostic
;
19 use errors
::FatalError
;
23 use ty
::query
::config
::{QueryConfig, QueryDescription}
;
24 use ty
::query
::job
::{QueryJob, QueryResult, QueryInfo}
;
27 use util
::common
::{profq_msg, ProfileQueriesMsg, QueryMsg}
;
29 use rustc_data_structures
::fx
::{FxHashMap}
;
30 use rustc_data_structures
::sync
::{Lrc, Lock}
;
33 use std
::collections
::hash_map
::Entry
;
35 use syntax
::source_map
::DUMMY_SP
;
37 pub struct QueryCache
<'tcx
, D
: QueryConfig
<'tcx
> + ?Sized
> {
38 pub(super) results
: FxHashMap
<D
::Key
, QueryValue
<D
::Value
>>,
39 pub(super) active
: FxHashMap
<D
::Key
, QueryResult
<'tcx
>>,
42 pub(super) struct QueryValue
<T
> {
44 pub(super) index
: DepNodeIndex
,
47 impl<T
> QueryValue
<T
> {
48 pub(super) fn new(value
: T
,
49 dep_node_index
: DepNodeIndex
)
53 index
: dep_node_index
,
58 impl<'tcx
, M
: QueryConfig
<'tcx
>> Default
for QueryCache
<'tcx
, M
> {
59 fn default() -> QueryCache
<'tcx
, M
> {
61 results
: FxHashMap
::default(),
62 active
: FxHashMap
::default(),
67 // If enabled, send a message to the profile-queries thread
68 macro_rules
! profq_msg
{
69 ($tcx
:expr
, $msg
:expr
) => {
70 if cfg
!(debug_assertions
) {
71 if $tcx
.sess
.profile_queries() {
72 profq_msg($tcx
.sess
, $msg
)
78 // If enabled, format a key using its debug string, which can be
79 // expensive to compute (in terms of time).
80 macro_rules
! profq_query_msg
{
81 ($query
:expr
, $tcx
:expr
, $key
:expr
) => {{
82 let msg
= if cfg
!(debug_assertions
) {
83 if $tcx
.sess
.profile_queries_and_keys() {
84 Some(format
!("{:?}", $key
))
94 /// A type representing the responsibility to execute the job in the `job` field.
95 /// This will poison the relevant query if dropped.
96 pub(super) struct JobOwner
<'a
, 'tcx
: 'a
, Q
: QueryDescription
<'tcx
> + 'a
> {
97 cache
: &'a Lock
<QueryCache
<'tcx
, Q
>>,
99 job
: Lrc
<QueryJob
<'tcx
>>,
102 impl<'a
, 'tcx
, Q
: QueryDescription
<'tcx
>> JobOwner
<'a
, 'tcx
, Q
> {
103 /// Either gets a JobOwner corresponding the the query, allowing us to
104 /// start executing the query, or it returns with the result of the query.
105 /// If the query is executing elsewhere, this will wait for it.
106 /// If the query panicked, this will silently panic.
108 /// This function is inlined because that results in a noticeable speedup
109 /// for some compile-time benchmarks.
111 pub(super) fn try_get(
112 tcx
: TyCtxt
<'a
, 'tcx
, '_
>,
115 ) -> TryGetJob
<'a
, 'tcx
, Q
> {
116 let cache
= Q
::query_cache(tcx
);
118 let mut lock
= cache
.borrow_mut();
119 if let Some(value
) = lock
.results
.get(key
) {
120 profq_msg
!(tcx
, ProfileQueriesMsg
::CacheHit
);
121 tcx
.sess
.profiler(|p
| {
122 p
.record_query(Q
::CATEGORY
);
123 p
.record_query_hit(Q
::CATEGORY
);
126 let result
= Ok((value
.value
.clone(), value
.index
));
127 return TryGetJob
::JobCompleted(result
);
129 let job
= match lock
.active
.entry((*key
).clone()) {
130 Entry
::Occupied(entry
) => {
132 QueryResult
::Started(ref job
) => job
.clone(),
133 QueryResult
::Poisoned
=> FatalError
.raise(),
136 Entry
::Vacant(entry
) => {
137 // No job entry for this query. Return a new one to be started later
138 return tls
::with_related_context(tcx
, |icx
| {
139 let info
= QueryInfo
{
141 query
: Q
::query(key
.clone()),
143 let job
= Lrc
::new(QueryJob
::new(info
, icx
.query
.clone()));
144 let owner
= JobOwner
{
149 entry
.insert(QueryResult
::Started(job
));
150 TryGetJob
::NotYetStarted(owner
)
156 if let Err(cycle
) = job
.await(tcx
, span
) {
157 return TryGetJob
::JobCompleted(Err(cycle
));
162 /// Completes the query by updating the query cache with the `result`,
163 /// signals the waiter and forgets the JobOwner, so it won't poison the query
164 pub(super) fn complete(self, result
: &Q
::Value
, dep_node_index
: DepNodeIndex
) {
165 // We can move out of `self` here because we `mem::forget` it below
166 let key
= unsafe { ptr::read(&self.key) }
;
167 let job
= unsafe { ptr::read(&self.job) }
;
168 let cache
= self.cache
;
170 // Forget ourself so our destructor won't poison the query
173 let value
= QueryValue
::new(result
.clone(), dep_node_index
);
175 let mut lock
= cache
.borrow_mut();
176 lock
.active
.remove(&key
);
177 lock
.results
.insert(key
, value
);
180 job
.signal_complete();
183 /// Executes a job by changing the ImplicitCtxt to point to the
184 /// new query job while it executes. It returns the diagnostics
185 /// captured during execution and the actual result.
186 pub(super) fn start
<'lcx
, F
, R
>(
188 tcx
: TyCtxt
<'_
, 'tcx
, 'lcx
>,
190 -> (R
, Vec
<Diagnostic
>)
192 F
: for<'b
> FnOnce(TyCtxt
<'b
, 'tcx
, 'lcx
>) -> R
194 // The TyCtxt stored in TLS has the same global interner lifetime
195 // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
196 // when accessing the ImplicitCtxt
197 let r
= tls
::with_related_context(tcx
, move |current_icx
| {
198 // Update the ImplicitCtxt to point to our new query job
199 let new_icx
= tls
::ImplicitCtxt
{
201 query
: Some(self.job
.clone()),
202 layout_depth
: current_icx
.layout_depth
,
203 task
: current_icx
.task
,
206 // Use the ImplicitCtxt while we execute the query
207 tls
::enter_context(&new_icx
, |_
| {
212 // Extract the diagnostic from the job
213 let diagnostics
= mem
::replace(&mut *self.job
.diagnostics
.lock(), Vec
::new());
219 impl<'a
, 'tcx
, Q
: QueryDescription
<'tcx
>> Drop
for JobOwner
<'a
, 'tcx
, Q
> {
221 // Poison the query so jobs waiting on it panic
222 self.cache
.borrow_mut().active
.insert(self.key
.clone(), QueryResult
::Poisoned
);
223 // Also signal the completion of the job, so waiters
224 // will continue execution
225 self.job
.signal_complete();
230 pub struct CycleError
<'tcx
> {
231 /// The query and related span which uses the cycle
232 pub(super) usage
: Option
<(Span
, Query
<'tcx
>)>,
233 pub(super) cycle
: Vec
<QueryInfo
<'tcx
>>,
236 /// The result of `try_get_lock`
237 pub(super) enum TryGetJob
<'a
, 'tcx
: 'a
, D
: QueryDescription
<'tcx
> + 'a
> {
238 /// The query is not yet started. Contains a guard to the cache eventually used to start it.
239 NotYetStarted(JobOwner
<'a
, 'tcx
, D
>),
241 /// The query was already completed.
242 /// Returns the result of the query and its dep node index
243 /// if it succeeded or a cycle error if it failed
244 JobCompleted(Result
<(D
::Value
, DepNodeIndex
), CycleError
<'tcx
>>),
247 impl<'a
, 'gcx
, 'tcx
> TyCtxt
<'a
, 'gcx
, 'tcx
> {
248 pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }
: CycleError
<'gcx
>)
249 -> DiagnosticBuilder
<'a
>
251 assert
!(!stack
.is_empty());
253 let fix_span
= |span
: Span
, query
: &Query
<'gcx
>| {
254 self.sess
.source_map().def_span(query
.default_span(self, span
))
257 // Disable naming impls with types in this path, since that
258 // sometimes cycles itself, leading to extra cycle errors.
259 // (And cycle errors around impls tend to occur during the
260 // collect/coherence phases anyhow.)
261 item_path
::with_forced_impl_filename_line(|| {
262 let span
= fix_span(stack
[1 % stack
.len()].span
, &stack
[0].query
);
263 let mut err
= struct_span_err
!(self.sess
,
266 "cycle detected when {}",
267 stack
[0].query
.describe(self));
269 for i
in 1..stack
.len() {
270 let query
= &stack
[i
].query
;
271 let span
= fix_span(stack
[(i
+ 1) % stack
.len()].span
, query
);
272 err
.span_note(span
, &format
!("...which requires {}...", query
.describe(self)));
275 err
.note(&format
!("...which again requires {}, completing the cycle",
276 stack
[0].query
.describe(self)));
278 if let Some((span
, query
)) = usage
{
279 err
.span_note(fix_span(span
, &query
),
280 &format
!("cycle used when {}", query
.describe(self)));
287 pub fn try_print_query_stack() {
288 eprintln
!("query stack during panic:");
290 tls
::with_context_opt(|icx
| {
291 if let Some(icx
) = icx
{
292 let mut current_query
= icx
.query
.clone();
295 while let Some(query
) = current_query
{
296 let mut db
= DiagnosticBuilder
::new(icx
.tcx
.sess
.diagnostic(),
298 &format
!("#{} [{}] {}",
300 query
.info
.query
.name(),
301 query
.info
.query
.describe(icx
.tcx
)));
302 db
.set_span(icx
.tcx
.sess
.source_map().def_span(query
.info
.span
));
303 icx
.tcx
.sess
.diagnostic().force_print_db(db
);
305 current_query
= query
.parent
.clone();
311 eprintln
!("end of query stack");
314 /// Try to read a node index for the node dep_node.
315 /// A node will have an index, when it's already been marked green, or when we can mark it
316 /// green. This function will mark the current task as a reader of the specified node, when
317 /// the a node index can be found for that node.
318 pub(super) fn try_mark_green_and_read(self, dep_node
: &DepNode
) -> Option
<DepNodeIndex
> {
319 match self.dep_graph
.node_color(dep_node
) {
320 Some(DepNodeColor
::Green(dep_node_index
)) => {
321 self.dep_graph
.read_index(dep_node_index
);
324 Some(DepNodeColor
::Red
) => {
328 // try_mark_green (called below) will panic when full incremental
329 // compilation is disabled. If that's the case, we can't try to mark nodes
330 // as green anyway, so we can safely return None here.
331 if !self.dep_graph
.is_fully_enabled() {
334 match self.dep_graph
.try_mark_green(self.global_tcx(), &dep_node
) {
335 Some(dep_node_index
) => {
336 debug_assert
!(self.dep_graph
.is_green(&dep_node
));
337 self.dep_graph
.read_index(dep_node_index
);
348 fn try_get_with
<Q
: QueryDescription
<'gcx
>>(
352 -> Result
<Q
::Value
, CycleError
<'gcx
>>
354 debug
!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
360 ProfileQueriesMsg
::QueryBegin(
362 profq_query_msg
!(Q
::NAME
, self, key
),
366 self.sess
.profiler(|p
| p
.record_query(Q
::CATEGORY
));
368 let job
= match JobOwner
::try_get(self, span
, &key
) {
369 TryGetJob
::NotYetStarted(job
) => job
,
370 TryGetJob
::JobCompleted(result
) => {
371 return result
.map(|(v
, index
)| {
372 self.sess
.profiler(|p
| p
.record_query_hit(Q
::CATEGORY
));
373 self.dep_graph
.read_index(index
);
379 // Fast path for when incr. comp. is off. `to_dep_node` is
380 // expensive for some DepKinds.
381 if !self.dep_graph
.is_fully_enabled() {
382 let null_dep_node
= DepNode
::new_no_params(::dep_graph
::DepKind
::Null
);
383 return self.force_query_with_job
::<Q
>(key
, job
, null_dep_node
).map(|(v
, _
)| v
);
386 let dep_node
= Q
::to_dep_node(self, &key
);
388 if dep_node
.kind
.is_anon() {
389 profq_msg
!(self, ProfileQueriesMsg
::ProviderBegin
);
390 self.sess
.profiler(|p
| p
.start_activity(Q
::CATEGORY
));
392 let res
= job
.start(self, |tcx
| {
393 tcx
.dep_graph
.with_anon_task(dep_node
.kind
, || {
394 Q
::compute(tcx
.global_tcx(), key
)
398 self.sess
.profiler(|p
| p
.end_activity(Q
::CATEGORY
));
399 profq_msg
!(self, ProfileQueriesMsg
::ProviderEnd
);
400 let ((result
, dep_node_index
), diagnostics
) = res
;
402 self.dep_graph
.read_index(dep_node_index
);
404 self.queries
.on_disk_cache
405 .store_diagnostics_for_anon_node(dep_node_index
, diagnostics
);
407 job
.complete(&result
, dep_node_index
);
412 if !dep_node
.kind
.is_input() {
413 if let Some(dep_node_index
) = self.try_mark_green_and_read(&dep_node
) {
414 profq_msg
!(self, ProfileQueriesMsg
::CacheHit
);
415 self.sess
.profiler(|p
| p
.record_query_hit(Q
::CATEGORY
));
417 return self.load_from_disk_and_cache_in_memory
::<Q
>(key
,
424 match self.force_query_with_job
::<Q
>(key
, job
, dep_node
) {
425 Ok((result
, dep_node_index
)) => {
426 self.dep_graph
.read_index(dep_node_index
);
433 fn load_from_disk_and_cache_in_memory
<Q
: QueryDescription
<'gcx
>>(
436 job
: JobOwner
<'a
, 'gcx
, Q
>,
437 dep_node_index
: DepNodeIndex
,
439 ) -> Result
<Q
::Value
, CycleError
<'gcx
>>
441 // Note this function can be called concurrently from the same query
442 // We must ensure that this is handled correctly
444 debug_assert
!(self.dep_graph
.is_green(dep_node
));
446 // First we try to load the result from the on-disk cache
447 let result
= if Q
::cache_on_disk(key
.clone()) &&
448 self.sess
.opts
.debugging_opts
.incremental_queries
{
449 let prev_dep_node_index
=
450 self.dep_graph
.prev_dep_node_index_of(dep_node
);
451 let result
= Q
::try_load_from_disk(self.global_tcx(),
452 prev_dep_node_index
);
454 // We always expect to find a cached result for things that
455 // can be forced from DepNode.
456 debug_assert
!(!dep_node
.kind
.can_reconstruct_query_key() ||
458 "Missing on-disk cache entry for {:?}",
462 // Some things are never cached on disk.
466 let result
= if let Some(result
) = result
{
469 // We could not load a result from the on-disk cache, so
472 // The diagnostics for this query have already been
473 // promoted to the current session during
474 // try_mark_green(), so we can ignore them here.
475 let (result
, _
) = job
.start(self, |tcx
| {
476 // The dep-graph for this computation is already in
478 tcx
.dep_graph
.with_ignore(|| {
485 // If -Zincremental-verify-ich is specified, re-hash results from
486 // the cache and make sure that they have the expected fingerprint.
487 if self.sess
.opts
.debugging_opts
.incremental_verify_ich
{
488 use rustc_data_structures
::stable_hasher
::{StableHasher, HashStable}
;
489 use ich
::Fingerprint
;
491 assert
!(Some(self.dep_graph
.fingerprint_of(dep_node_index
)) ==
492 self.dep_graph
.prev_fingerprint_of(dep_node
),
493 "Fingerprint for green query instance not loaded \
494 from cache: {:?}", dep_node
);
496 debug
!("BEGIN verify_ich({:?})", dep_node
);
497 let mut hcx
= self.create_stable_hashing_context();
498 let mut hasher
= StableHasher
::new();
500 result
.hash_stable(&mut hcx
, &mut hasher
);
502 let new_hash
: Fingerprint
= hasher
.finish();
503 debug
!("END verify_ich({:?})", dep_node
);
505 let old_hash
= self.dep_graph
.fingerprint_of(dep_node_index
);
507 assert
!(new_hash
== old_hash
, "Found unstable fingerprints \
508 for {:?}", dep_node
);
511 if self.sess
.opts
.debugging_opts
.query_dep_graph
{
512 self.dep_graph
.mark_loaded_from_cache(dep_node_index
, true);
515 job
.complete(&result
, dep_node_index
);
520 fn force_query_with_job
<Q
: QueryDescription
<'gcx
>>(
523 job
: JobOwner
<'_
, 'gcx
, Q
>,
525 -> Result
<(Q
::Value
, DepNodeIndex
), CycleError
<'gcx
>> {
526 // If the following assertion triggers, it can have two reasons:
527 // 1. Something is wrong with DepNode creation, either here or
528 // in DepGraph::try_mark_green()
529 // 2. Two distinct query keys get mapped to the same DepNode
530 // (see for example #48923)
531 assert
!(!self.dep_graph
.dep_node_exists(&dep_node
),
532 "Forcing query with already existing DepNode.\n\
537 profq_msg
!(self, ProfileQueriesMsg
::ProviderBegin
);
538 self.sess
.profiler(|p
| {
539 p
.start_activity(Q
::CATEGORY
);
540 p
.record_query(Q
::CATEGORY
);
543 let res
= job
.start(self, |tcx
| {
544 if dep_node
.kind
.is_eval_always() {
545 tcx
.dep_graph
.with_eval_always_task(dep_node
,
550 tcx
.dep_graph
.with_task(dep_node
,
557 self.sess
.profiler(|p
| p
.end_activity(Q
::CATEGORY
));
558 profq_msg
!(self, ProfileQueriesMsg
::ProviderEnd
);
560 let ((result
, dep_node_index
), diagnostics
) = res
;
562 if self.sess
.opts
.debugging_opts
.query_dep_graph
{
563 self.dep_graph
.mark_loaded_from_cache(dep_node_index
, false);
566 if dep_node
.kind
!= ::dep_graph
::DepKind
::Null
{
567 self.queries
.on_disk_cache
568 .store_diagnostics(dep_node_index
, diagnostics
);
571 job
.complete(&result
, dep_node_index
);
573 Ok((result
, dep_node_index
))
576 /// Ensure that either this query has all green inputs or been executed.
577 /// Executing query::ensure(D) is considered a read of the dep-node D.
579 /// This function is particularly useful when executing passes for their
580 /// side-effects -- e.g., in order to report errors for erroneous programs.
582 /// Note: The optimization is only available during incr. comp.
583 pub(super) fn ensure_query
<Q
: QueryDescription
<'gcx
>>(self, key
: Q
::Key
) -> () {
584 let dep_node
= Q
::to_dep_node(self, &key
);
586 // Ensuring an "input" or anonymous query makes no sense
587 assert
!(!dep_node
.kind
.is_anon());
588 assert
!(!dep_node
.kind
.is_input());
589 if self.try_mark_green_and_read(&dep_node
).is_none() {
590 // A None return from `try_mark_green_and_read` means that this is either
591 // a new dep node or that the dep node has already been marked red.
592 // Either way, we can't call `dep_graph.read()` as we don't have the
593 // DepNodeIndex. We must invoke the query itself. The performance cost
594 // this introduces should be negligible as we'll immediately hit the
595 // in-memory cache, or another query down the line will.
597 self.sess
.profiler(|p
| {
598 p
.start_activity(Q
::CATEGORY
);
599 p
.record_query(Q
::CATEGORY
);
602 let _
= self.get_query
::<Q
>(DUMMY_SP
, key
);
604 self.sess
.profiler(|p
| p
.end_activity(Q
::CATEGORY
));
609 fn force_query
<Q
: QueryDescription
<'gcx
>>(
614 ) -> Result
<(Q
::Value
, DepNodeIndex
), CycleError
<'gcx
>> {
615 // We may be concurrently trying both execute and force a query
616 // Ensure that only one of them runs the query
617 let job
= match JobOwner
::try_get(self, span
, &key
) {
618 TryGetJob
::NotYetStarted(job
) => job
,
619 TryGetJob
::JobCompleted(result
) => return result
,
621 self.force_query_with_job
::<Q
>(key
, job
, dep_node
)
624 pub(super) fn try_get_query
<Q
: QueryDescription
<'gcx
>>(
628 ) -> Result
<Q
::Value
, DiagnosticBuilder
<'a
>> {
629 match self.try_get_with
::<Q
>(span
, key
) {
631 Err(e
) => Err(self.report_cycle(e
)),
635 pub(super) fn get_query
<Q
: QueryDescription
<'gcx
>>(
640 self.try_get_query
::<Q
>(span
, key
).unwrap_or_else(|mut e
| {
642 Q
::handle_cycle_error(self)
647 macro_rules
! handle_cycle_error
{
648 ([][$this
: expr
]) => {{
649 Value
::from_cycle_error($this
.global_tcx())
651 ([fatal_cycle$
(, $modifiers
:ident
)*][$this
:expr
]) => {{
652 $this
.sess
.abort_if_errors();
655 ([$other
:ident$
(, $modifiers
:ident
)*][$
($args
:tt
)*]) => {
656 handle_cycle_error
!([$
($modifiers
),*][$
($args
)*])
660 macro_rules
! define_queries
{
661 (<$tcx
:tt
> $
($category
:tt
{
662 $
($
(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*
664 define_queries_inner
! { <$tcx
>
665 $
($
( $
(#[$attr])* category<$category> [$($modifiers)*] fn $name: $node($K) -> $V,)*)*
670 macro_rules
! define_queries_inner
{
672 $
($
(#[$attr:meta])* category<$category:tt>
673 [$
($modifiers
:tt
)*] fn $name
:ident
: $node
:ident($K
:ty
) -> $V
:ty
,)*) => {
676 #[cfg(parallel_queries)]
677 use ty
::query
::job
::QueryResult
;
678 use rustc_data_structures
::sync
::Lock
;
680 rustc_data_structures
::stable_hasher
::HashStable
,
681 rustc_data_structures
::stable_hasher
::StableHasherResult
,
682 rustc_data_structures
::stable_hasher
::StableHasher
,
683 ich
::StableHashingContext
685 use util
::profiling
::ProfileCategory
;
687 define_queries_struct
! {
689 input
: ($
(([$
($modifiers
)*] [$
($attr
)*] [$name
]))*)
692 impl<$tcx
> Queries
<$tcx
> {
694 providers
: IndexVec
<CrateNum
, Providers
<$tcx
>>,
695 fallback_extern_providers
: Providers
<$tcx
>,
696 on_disk_cache
: OnDiskCache
<'tcx
>,
700 fallback_extern_providers
: Box
::new(fallback_extern_providers
),
702 $
($name
: Default
::default()),*
706 #[cfg(parallel_queries)]
707 pub fn collect_active_jobs(&self) -> Vec
<Lrc
<QueryJob
<$tcx
>>> {
708 let mut jobs
= Vec
::new();
710 // We use try_lock here since we are only called from the
711 // deadlock handler, and this shouldn't be locked
714 self.$name
.try_lock().unwrap().active
.values().filter_map(|v
|
715 if let QueryResult
::Started(ref job
) = *v
{
728 #[allow(nonstandard_style)]
729 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
730 pub enum Query
<$tcx
> {
731 $
($
(#[$attr])* $name($K)),*
734 impl<$tcx
> Query
<$tcx
> {
735 pub fn name(&self) -> &'
static str {
737 $
(Query
::$
name(_
) => stringify
!($name
),)*
741 pub fn describe(&self, tcx
: TyCtxt
<'_
, '_
, '_
>) -> Cow
<'
static, str> {
742 let (r
, name
) = match *self {
743 $
(Query
::$
name(key
) => {
744 (queries
::$name
::describe(tcx
, key
), stringify
!($name
))
747 if tcx
.sess
.verbose() {
748 format
!("{} [{}]", r
, name
).into()
754 // FIXME(eddyb) Get more valid Span's on queries.
755 pub fn default_span(&self, tcx
: TyCtxt
<'_
, $tcx
, '_
>, span
: Span
) -> Span
{
756 if !span
.is_dummy() {
759 // The def_span query is used to calculate default_span,
760 // so exit to avoid infinite recursion
761 if let Query
::def_span(..) = *self {
765 $
(Query
::$
name(key
) => key
.default_span(tcx
),)*
770 impl<'a
, $tcx
> HashStable
<StableHashingContext
<'a
>> for Query
<$tcx
> {
771 fn hash_stable
<W
: StableHasherResult
>(&self,
772 hcx
: &mut StableHashingContext
<'a
>,
773 hasher
: &mut StableHasher
<W
>) {
774 mem
::discriminant(self).hash_stable(hcx
, hasher
);
776 $
(Query
::$
name(key
) => key
.hash_stable(hcx
, hasher
),)*
782 use std
::marker
::PhantomData
;
784 $
(#[allow(nonstandard_style)]
785 pub struct $name
<$tcx
> {
786 data
: PhantomData
<&$
tcx ()>
790 // This module and the functions in it exist only to provide a
791 // predictable symbol name prefix for query providers. This is helpful
792 // for analyzing queries in profilers.
793 pub(super) mod __query_compute
{
795 pub fn $name
<F
: FnOnce() -> R
, R
>(f
: F
) -> R
{
800 $
(impl<$tcx
> QueryConfig
<$tcx
> for queries
::$name
<$tcx
> {
804 const NAME
: &'
static str = stringify
!($name
);
805 const CATEGORY
: ProfileCategory
= $category
;
808 impl<$tcx
> QueryAccessors
<$tcx
> for queries
::$name
<$tcx
> {
809 fn query(key
: Self::Key
) -> Query
<'tcx
> {
813 fn query_cache
<'a
>(tcx
: TyCtxt
<'a
, $tcx
, '_
>) -> &'a Lock
<QueryCache
<$tcx
, Self>> {
818 fn to_dep_node(tcx
: TyCtxt
<'_
, $tcx
, '_
>, key
: &Self::Key
) -> DepNode
{
819 use dep_graph
::DepConstructor
::*;
821 DepNode
::new(tcx
, $
node(*key
))
825 fn compute(tcx
: TyCtxt
<'_
, 'tcx
, '_
>, key
: Self::Key
) -> Self::Value
{
826 __query_compute
::$
name(move || {
827 let provider
= tcx
.queries
.providers
.get(key
.query_crate())
828 // HACK(eddyb) it's possible crates may be loaded after
829 // the query engine is created, and because crate loading
830 // is not yet integrated with the query engine, such crates
831 // would be be missing appropriate entries in `providers`.
832 .unwrap_or(&tcx
.queries
.fallback_extern_providers
)
834 provider(tcx
.global_tcx(), key
)
838 fn handle_cycle_error(tcx
: TyCtxt
<'_
, 'tcx
, '_
>) -> Self::Value
{
839 handle_cycle_error
!([$
($modifiers
)*][tcx
])
843 impl<'a
, $tcx
, 'lcx
> queries
::$name
<$tcx
> {
844 /// Ensure that either this query has all green inputs or been executed.
845 /// Executing query::ensure(D) is considered a read of the dep-node D.
847 /// This function is particularly useful when executing passes for their
848 /// side-effects -- e.g., in order to report errors for erroneous programs.
850 /// Note: The optimization is only available during incr. comp.
851 pub fn ensure(tcx
: TyCtxt
<'a
, $tcx
, 'lcx
>, key
: $K
) -> () {
852 tcx
.ensure_query
::<queries
::$name
<'_
>>(key
);
856 #[derive(Copy, Clone)]
857 pub struct TyCtxtAt
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
858 pub tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
862 impl<'a
, 'gcx
, 'tcx
> Deref
for TyCtxtAt
<'a
, 'gcx
, 'tcx
> {
863 type Target
= TyCtxt
<'a
, 'gcx
, 'tcx
>;
864 fn deref(&self) -> &Self::Target
{
869 impl<'a
, $tcx
, 'lcx
> TyCtxt
<'a
, $tcx
, 'lcx
> {
870 /// Return a transparent wrapper for `TyCtxt` which uses
871 /// `span` as the location of queries performed through it.
872 pub fn at(self, span
: Span
) -> TyCtxtAt
<'a
, $tcx
, 'lcx
> {
880 pub fn $
name(self, key
: $K
) -> $V
{
881 self.at(DUMMY_SP
).$
name(key
)
885 impl<'a
, $tcx
, 'lcx
> TyCtxtAt
<'a
, $tcx
, 'lcx
> {
887 pub fn $
name(self, key
: $K
) -> $V
{
888 self.tcx
.get_query
::<queries
::$name
<'_
>>(self.span
, key
)
892 define_provider_struct
! {
894 input
: ($
(([$
($modifiers
)*] [$name
] [$K
] [$V
]))*)
897 impl<$tcx
> Copy
for Providers
<$tcx
> {}
898 impl<$tcx
> Clone
for Providers
<$tcx
> {
899 fn clone(&self) -> Self { *self }
904 macro_rules
! define_queries_struct
{
906 input
: ($
(([$
($modifiers
:tt
)*] [$
($attr
:tt
)*] [$name
:ident
]))*)) => {
907 pub(crate) struct Queries
<$tcx
> {
908 /// This provides access to the incr. comp. on-disk cache for query results.
909 /// Do not access this directly. It is only meant to be used by
910 /// `DepGraph::try_mark_green()` and the query infrastructure.
911 pub(crate) on_disk_cache
: OnDiskCache
<'tcx
>,
913 providers
: IndexVec
<CrateNum
, Providers
<$tcx
>>,
914 fallback_extern_providers
: Box
<Providers
<$tcx
>>,
916 $
($
(#[$attr])* $name: Lock<QueryCache<$tcx, queries::$name<$tcx>>>,)*
921 macro_rules
! define_provider_struct
{
923 input
: ($
(([$
($modifiers
:tt
)*] [$name
:ident
] [$K
:ty
] [$R
:ty
]))*)) => {
924 pub struct Providers
<$tcx
> {
925 $
(pub $name
: for<'a
> fn(TyCtxt
<'a
, $tcx
, $tcx
>, $K
) -> $R
,)*
928 impl<$tcx
> Default
for Providers
<$tcx
> {
929 fn default() -> Self {
930 $
(fn $name
<'a
, $tcx
>(_
: TyCtxt
<'a
, $tcx
, $tcx
>, key
: $K
) -> $R
{
931 bug
!("tcx.{}({:?}) unsupported by its crate",
932 stringify
!($name
), key
);
934 Providers { $($name),* }
941 /// The red/green evaluation system will try to mark a specific DepNode in the
942 /// dependency graph as green by recursively trying to mark the dependencies of
943 /// that DepNode as green. While doing so, it will sometimes encounter a DepNode
944 /// where we don't know if it is red or green and we therefore actually have
945 /// to recompute its value in order to find out. Since the only piece of
946 /// information that we have at that point is the DepNode we are trying to
947 /// re-evaluate, we need some way to re-run a query from just that. This is what
948 /// `force_from_dep_node()` implements.
950 /// In the general case, a DepNode consists of a DepKind and an opaque
951 /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
952 /// is usually constructed by computing a stable hash of the query-key that the
953 /// DepNode corresponds to. Consequently, it is not in general possible to go
954 /// back from hash to query-key (since hash functions are not reversible). For
955 /// this reason `force_from_dep_node()` is expected to fail from time to time
956 /// because we just cannot find out, from the DepNode alone, what the
957 /// corresponding query-key is and therefore cannot re-run the query.
959 /// The system deals with this case letting `try_mark_green` fail which forces
960 /// the root query to be re-evaluated.
962 /// Now, if force_from_dep_node() would always fail, it would be pretty useless.
963 /// Fortunately, we can use some contextual information that will allow us to
964 /// reconstruct query-keys for certain kinds of DepNodes. In particular, we
965 /// enforce by construction that the GUID/fingerprint of certain DepNodes is a
966 /// valid DefPathHash. Since we also always build a huge table that maps every
967 /// DefPathHash in the current codebase to the corresponding DefId, we have
968 /// everything we need to re-run the query.
970 /// Take the `mir_validated` query as an example. Like many other queries, it
971 /// just has a single parameter: the DefId of the item it will compute the
972 /// validated MIR for. Now, when we call `force_from_dep_node()` on a dep-node
973 /// with kind `MirValidated`, we know that the GUID/fingerprint of the dep-node
974 /// is actually a DefPathHash, and can therefore just look up the corresponding
975 /// DefId in `tcx.def_path_hash_to_def_id`.
977 /// When you implement a new query, it will likely have a corresponding new
978 /// DepKind, and you'll have to support it here in `force_from_dep_node()`. As
979 /// a rule of thumb, if your query takes a DefId or DefIndex as sole parameter,
980 /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
981 /// add it to the "We don't have enough information to reconstruct..." group in
983 pub fn force_from_dep_node
<'a
, 'gcx
, 'lcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'lcx
>,
986 use hir
::def_id
::LOCAL_CRATE
;
988 // We must avoid ever having to call force_from_dep_node() for a
989 // DepNode::CodegenUnit:
990 // Since we cannot reconstruct the query key of a DepNode::CodegenUnit, we
991 // would always end up having to evaluate the first caller of the
992 // `codegen_unit` query that *is* reconstructible. This might very well be
993 // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
994 // to re-trigger calling the `codegen_unit` query with the right key. At
995 // that point we would already have re-done all the work we are trying to
996 // avoid doing in the first place.
997 // The solution is simple: Just explicitly call the `codegen_unit` query for
998 // each CGU, right after partitioning. This way `try_mark_green` will always
999 // hit the cache instead of having to go through `force_from_dep_node`.
1000 // This assertion makes sure, we actually keep applying the solution above.
1001 debug_assert
!(dep_node
.kind
!= DepKind
::CodegenUnit
,
1002 "calling force_from_dep_node() on DepKind::CodegenUnit");
1004 if !dep_node
.kind
.can_reconstruct_query_key() {
1008 macro_rules
! def_id
{
1010 if let Some(def_id
) = dep_node
.extract_def_id(tcx
) {
1013 // return from the whole function
1019 macro_rules
! krate
{
1020 () => { (def_id!()).krate }
1023 macro_rules
! force
{
1024 ($query
:ident
, $key
:expr
) => {
1026 use $
crate::util
::common
::{ProfileQueriesMsg, profq_msg}
;
1029 ProfileQueriesMsg
::QueryBegin(
1031 profq_query_msg
!(::ty
::query
::queries
::$query
::NAME
, tcx
, $key
),
1035 if let Err(e
) = tcx
.force_query
::<::ty
::query
::queries
::$query
<'_
>>(
1036 $key
, DUMMY_SP
, *dep_node
1038 tcx
.report_cycle(e
).emit();
1044 // FIXME(#45015): We should try move this boilerplate code into a macro
1046 match dep_node
.kind
{
1047 // These are inputs that are expected to be pre-allocated and that
1048 // should therefore always be red or green already
1049 DepKind
::AllLocalTraitImpls
|
1051 DepKind
::CrateMetadata
|
1055 // This are anonymous nodes
1056 DepKind
::TraitSelect
|
1058 // We don't have enough information to reconstruct the query key of
1063 DepKind
::NeedsDrop
|
1065 DepKind
::ConstEval
|
1066 DepKind
::InstanceSymbolName
|
1068 DepKind
::BorrowCheckKrate
|
1069 DepKind
::Specializes
|
1070 DepKind
::ImplementationsOfTrait
|
1071 DepKind
::TypeParamPredicates
|
1072 DepKind
::CodegenUnit
|
1073 DepKind
::CompileCodegenUnit
|
1074 DepKind
::FulfillObligation
|
1075 DepKind
::VtableMethods
|
1076 DepKind
::EraseRegionsTy
|
1077 DepKind
::NormalizeProjectionTy
|
1078 DepKind
::NormalizeTyAfterErasingRegions
|
1079 DepKind
::ImpliedOutlivesBounds
|
1080 DepKind
::DropckOutlives
|
1081 DepKind
::EvaluateObligation
|
1082 DepKind
::TypeOpAscribeUserType
|
1084 DepKind
::TypeOpSubtype
|
1085 DepKind
::TypeOpProvePredicate
|
1086 DepKind
::TypeOpNormalizeTy
|
1087 DepKind
::TypeOpNormalizePredicate
|
1088 DepKind
::TypeOpNormalizePolyFnSig
|
1089 DepKind
::TypeOpNormalizeFnSig
|
1090 DepKind
::SubstituteNormalizeAndTestPredicates
|
1091 DepKind
::InstanceDefSizeEstimate
|
1092 DepKind
::ProgramClausesForEnv
|
1094 // This one should never occur in this context
1096 bug
!("force_from_dep_node() - Encountered {:?}", dep_node
)
1099 // These are not queries
1100 DepKind
::CoherenceCheckTrait
|
1101 DepKind
::ItemVarianceConstraints
=> {
1105 DepKind
::RegionScopeTree
=> { force!(region_scope_tree, def_id!()); }
1107 DepKind
::Coherence
=> { force!(crate_inherent_impls, LOCAL_CRATE); }
1108 DepKind
::CoherenceInherentImplOverlapCheck
=> {
1109 force
!(crate_inherent_impls_overlap_check
, LOCAL_CRATE
)
1111 DepKind
::PrivacyAccessLevels
=> { force!(privacy_access_levels, LOCAL_CRATE); }
1112 DepKind
::MirBuilt
=> { force!(mir_built, def_id!()); }
1113 DepKind
::MirConstQualif
=> { force!(mir_const_qualif, def_id!()); }
1114 DepKind
::MirConst
=> { force!(mir_const, def_id!()); }
1115 DepKind
::MirValidated
=> { force!(mir_validated, def_id!()); }
1116 DepKind
::MirOptimized
=> { force!(optimized_mir, def_id!()); }
1118 DepKind
::BorrowCheck
=> { force!(borrowck, def_id!()); }
1119 DepKind
::MirBorrowCheck
=> { force!(mir_borrowck, def_id!()); }
1120 DepKind
::UnsafetyCheckResult
=> { force!(unsafety_check_result, def_id!()); }
1121 DepKind
::UnsafeDeriveOnReprPacked
=> { force!(unsafe_derive_on_repr_packed, def_id!()); }
1122 DepKind
::Reachability
=> { force!(reachable_set, LOCAL_CRATE); }
1123 DepKind
::MirKeys
=> { force!(mir_keys, LOCAL_CRATE); }
1124 DepKind
::CrateVariances
=> { force!(crate_variances, LOCAL_CRATE); }
1125 DepKind
::AssociatedItems
=> { force!(associated_item, def_id!()); }
1126 DepKind
::TypeOfItem
=> { force!(type_of, def_id!()); }
1127 DepKind
::GenericsOfItem
=> { force!(generics_of, def_id!()); }
1128 DepKind
::PredicatesOfItem
=> { force!(predicates_of, def_id!()); }
1129 DepKind
::PredicatesDefinedOnItem
=> { force!(predicates_defined_on, def_id!()); }
1130 DepKind
::ExplicitPredicatesOfItem
=> { force!(explicit_predicates_of, def_id!()); }
1131 DepKind
::InferredOutlivesOf
=> { force!(inferred_outlives_of, def_id!()); }
1132 DepKind
::InferredOutlivesCrate
=> { force!(inferred_outlives_crate, LOCAL_CRATE); }
1133 DepKind
::SuperPredicatesOfItem
=> { force!(super_predicates_of, def_id!()); }
1134 DepKind
::TraitDefOfItem
=> { force!(trait_def, def_id!()); }
1135 DepKind
::AdtDefOfItem
=> { force!(adt_def, def_id!()); }
1136 DepKind
::ImplTraitRef
=> { force!(impl_trait_ref, def_id!()); }
1137 DepKind
::ImplPolarity
=> { force!(impl_polarity, def_id!()); }
1138 DepKind
::FnSignature
=> { force!(fn_sig, def_id!()); }
1139 DepKind
::CoerceUnsizedInfo
=> { force!(coerce_unsized_info, def_id!()); }
1140 DepKind
::ItemVariances
=> { force!(variances_of, def_id!()); }
1141 DepKind
::IsConstFn
=> { force!(is_const_fn_raw, def_id!()); }
1142 DepKind
::IsPromotableConstFn
=> { force!(is_promotable_const_fn, def_id!()); }
1143 DepKind
::IsForeignItem
=> { force!(is_foreign_item, def_id!()); }
1144 DepKind
::SizedConstraint
=> { force!(adt_sized_constraint, def_id!()); }
1145 DepKind
::DtorckConstraint
=> { force!(adt_dtorck_constraint, def_id!()); }
1146 DepKind
::AdtDestructor
=> { force!(adt_destructor, def_id!()); }
1147 DepKind
::AssociatedItemDefIds
=> { force!(associated_item_def_ids, def_id!()); }
1148 DepKind
::InherentImpls
=> { force!(inherent_impls, def_id!()); }
1149 DepKind
::TypeckBodiesKrate
=> { force!(typeck_item_bodies, LOCAL_CRATE); }
1150 DepKind
::TypeckTables
=> { force!(typeck_tables_of, def_id!()); }
1151 DepKind
::UsedTraitImports
=> { force!(used_trait_imports, def_id!()); }
1152 DepKind
::HasTypeckTables
=> { force!(has_typeck_tables, def_id!()); }
1153 DepKind
::SymbolName
=> { force!(def_symbol_name, def_id!()); }
1154 DepKind
::SpecializationGraph
=> { force!(specialization_graph_of, def_id!()); }
1155 DepKind
::ObjectSafety
=> { force!(is_object_safe, def_id!()); }
1156 DepKind
::TraitImpls
=> { force!(trait_impls_of, def_id!()); }
1157 DepKind
::CheckMatch
=> { force!(check_match, def_id!()); }
1159 DepKind
::ParamEnv
=> { force!(param_env, def_id!()); }
1160 DepKind
::Environment
=> { force!(environment, def_id!()); }
1161 DepKind
::DescribeDef
=> { force!(describe_def, def_id!()); }
1162 DepKind
::DefSpan
=> { force!(def_span, def_id!()); }
1163 DepKind
::LookupStability
=> { force!(lookup_stability, def_id!()); }
1164 DepKind
::LookupDeprecationEntry
=> {
1165 force
!(lookup_deprecation_entry
, def_id
!());
1167 DepKind
::ConstIsRvaluePromotableToStatic
=> {
1168 force
!(const_is_rvalue_promotable_to_static
, def_id
!());
1170 DepKind
::RvaluePromotableMap
=> { force!(rvalue_promotable_map, def_id!()); }
1171 DepKind
::ImplParent
=> { force!(impl_parent, def_id!()); }
1172 DepKind
::TraitOfItem
=> { force!(trait_of_item, def_id!()); }
1173 DepKind
::IsReachableNonGeneric
=> { force!(is_reachable_non_generic, def_id!()); }
1174 DepKind
::IsUnreachableLocalDefinition
=> {
1175 force
!(is_unreachable_local_definition
, def_id
!());
1177 DepKind
::IsMirAvailable
=> { force!(is_mir_available, def_id!()); }
1178 DepKind
::ItemAttrs
=> { force!(item_attrs, def_id!()); }
1179 DepKind
::CodegenFnAttrs
=> { force!(codegen_fn_attrs, def_id!()); }
1180 DepKind
::FnArgNames
=> { force!(fn_arg_names, def_id!()); }
1181 DepKind
::RenderedConst
=> { force!(rendered_const, def_id!()); }
1182 DepKind
::DylibDepFormats
=> { force!(dylib_dependency_formats, krate!()); }
1183 DepKind
::IsPanicRuntime
=> { force!(is_panic_runtime, krate!()); }
1184 DepKind
::IsCompilerBuiltins
=> { force!(is_compiler_builtins, krate!()); }
1185 DepKind
::HasGlobalAllocator
=> { force!(has_global_allocator, krate!()); }
1186 DepKind
::HasPanicHandler
=> { force!(has_panic_handler, krate!()); }
1187 DepKind
::ExternCrate
=> { force!(extern_crate, def_id!()); }
1188 DepKind
::LintLevels
=> { force!(lint_levels, LOCAL_CRATE); }
1189 DepKind
::InScopeTraits
=> { force!(in_scope_traits_map, def_id!().index); }
1190 DepKind
::ModuleExports
=> { force!(module_exports, def_id!()); }
1191 DepKind
::IsSanitizerRuntime
=> { force!(is_sanitizer_runtime, krate!()); }
1192 DepKind
::IsProfilerRuntime
=> { force!(is_profiler_runtime, krate!()); }
1193 DepKind
::GetPanicStrategy
=> { force!(panic_strategy, krate!()); }
1194 DepKind
::IsNoBuiltins
=> { force!(is_no_builtins, krate!()); }
1195 DepKind
::ImplDefaultness
=> { force!(impl_defaultness, def_id!()); }
1196 DepKind
::CheckItemWellFormed
=> { force!(check_item_well_formed, def_id!()); }
1197 DepKind
::CheckTraitItemWellFormed
=> { force!(check_trait_item_well_formed, def_id!()); }
1198 DepKind
::CheckImplItemWellFormed
=> { force!(check_impl_item_well_formed, def_id!()); }
1199 DepKind
::ReachableNonGenerics
=> { force!(reachable_non_generics, krate!()); }
1200 DepKind
::NativeLibraries
=> { force!(native_libraries, krate!()); }
1201 DepKind
::PluginRegistrarFn
=> { force!(plugin_registrar_fn, krate!()); }
1202 DepKind
::DeriveRegistrarFn
=> { force!(derive_registrar_fn, krate!()); }
1203 DepKind
::CrateDisambiguator
=> { force!(crate_disambiguator, krate!()); }
1204 DepKind
::CrateHash
=> { force!(crate_hash, krate!()); }
1205 DepKind
::OriginalCrateName
=> { force!(original_crate_name, krate!()); }
1206 DepKind
::ExtraFileName
=> { force!(extra_filename, krate!()); }
1208 DepKind
::AllTraitImplementations
=> {
1209 force
!(all_trait_implementations
, krate
!());
1212 DepKind
::DllimportForeignItems
=> {
1213 force
!(dllimport_foreign_items
, krate
!());
1215 DepKind
::IsDllimportForeignItem
=> {
1216 force
!(is_dllimport_foreign_item
, def_id
!());
1218 DepKind
::IsStaticallyIncludedForeignItem
=> {
1219 force
!(is_statically_included_foreign_item
, def_id
!());
1221 DepKind
::NativeLibraryKind
=> { force!(native_library_kind, def_id!()); }
1222 DepKind
::LinkArgs
=> { force!(link_args, LOCAL_CRATE); }
1224 DepKind
::ResolveLifetimes
=> { force!(resolve_lifetimes, krate!()); }
1225 DepKind
::NamedRegion
=> { force!(named_region_map, def_id!().index); }
1226 DepKind
::IsLateBound
=> { force!(is_late_bound_map, def_id!().index); }
1227 DepKind
::ObjectLifetimeDefaults
=> {
1228 force
!(object_lifetime_defaults_map
, def_id
!().index
);
1231 DepKind
::Visibility
=> { force!(visibility, def_id!()); }
1232 DepKind
::DepKind
=> { force!(dep_kind, krate!()); }
1233 DepKind
::CrateName
=> { force!(crate_name, krate!()); }
1234 DepKind
::ItemChildren
=> { force!(item_children, def_id!()); }
1235 DepKind
::ExternModStmtCnum
=> { force!(extern_mod_stmt_cnum, def_id!()); }
1236 DepKind
::GetLibFeatures
=> { force!(get_lib_features, LOCAL_CRATE); }
1237 DepKind
::DefinedLibFeatures
=> { force!(defined_lib_features, krate!()); }
1238 DepKind
::GetLangItems
=> { force!(get_lang_items, LOCAL_CRATE); }
1239 DepKind
::DefinedLangItems
=> { force!(defined_lang_items, krate!()); }
1240 DepKind
::MissingLangItems
=> { force!(missing_lang_items, krate!()); }
1241 DepKind
::VisibleParentMap
=> { force!(visible_parent_map, LOCAL_CRATE); }
1242 DepKind
::MissingExternCrateItem
=> {
1243 force
!(missing_extern_crate_item
, krate
!());
1245 DepKind
::UsedCrateSource
=> { force!(used_crate_source, krate!()); }
1246 DepKind
::PostorderCnums
=> { force!(postorder_cnums, LOCAL_CRATE); }
1248 DepKind
::Freevars
=> { force!(freevars, def_id!()); }
1249 DepKind
::MaybeUnusedTraitImport
=> {
1250 force
!(maybe_unused_trait_import
, def_id
!());
1252 DepKind
::MaybeUnusedExternCrates
=> { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
1253 DepKind
::StabilityIndex
=> { force!(stability_index, LOCAL_CRATE); }
1254 DepKind
::AllTraits
=> { force!(all_traits, LOCAL_CRATE); }
1255 DepKind
::AllCrateNums
=> { force!(all_crate_nums, LOCAL_CRATE); }
1256 DepKind
::ExportedSymbols
=> { force!(exported_symbols, krate!()); }
1257 DepKind
::CollectAndPartitionMonoItems
=> {
1258 force
!(collect_and_partition_mono_items
, LOCAL_CRATE
);
1260 DepKind
::IsCodegenedItem
=> { force!(is_codegened_item, def_id!()); }
1261 DepKind
::OutputFilenames
=> { force!(output_filenames, LOCAL_CRATE); }
1263 DepKind
::TargetFeaturesWhitelist
=> { force!(target_features_whitelist, LOCAL_CRATE); }
1265 DepKind
::Features
=> { force!(features_query, LOCAL_CRATE); }
1267 DepKind
::ProgramClausesFor
=> { force!(program_clauses_for, def_id!()); }
1268 DepKind
::WasmImportModuleMap
=> { force!(wasm_import_module_map, krate!()); }
1269 DepKind
::ForeignModules
=> { force!(foreign_modules, krate!()); }
1271 DepKind
::UpstreamMonomorphizations
=> {
1272 force
!(upstream_monomorphizations
, krate
!());
1274 DepKind
::UpstreamMonomorphizationsFor
=> {
1275 force
!(upstream_monomorphizations_for
, def_id
!());
1283 // FIXME(#45015): Another piece of boilerplate code that could be generated in
1284 // a combined define_dep_nodes!()/define_queries!() macro.
1285 macro_rules
! impl_load_from_cache
{
1286 ($
($dep_kind
:ident
=> $query_name
:ident
,)*) => {
1288 // Check whether the query invocation corresponding to the given
1289 // DepNode is eligible for on-disk-caching.
1290 pub fn cache_on_disk(&self, tcx
: TyCtxt
<'_
, '_
, '_
>) -> bool
{
1291 use ty
::query
::queries
;
1292 use ty
::query
::QueryDescription
;
1295 $
(DepKind
::$dep_kind
=> {
1296 let def_id
= self.extract_def_id(tcx
).unwrap();
1297 queries
::$query_name
::cache_on_disk(def_id
)
1303 // This is method will execute the query corresponding to the given
1304 // DepNode. It is only expected to work for DepNodes where the
1305 // above `cache_on_disk` methods returns true.
1306 // Also, as a sanity check, it expects that the corresponding query
1307 // invocation has been marked as green already.
1308 pub fn load_from_on_disk_cache(&self, tcx
: TyCtxt
<'_
, '_
, '_
>) {
1310 $
(DepKind
::$dep_kind
=> {
1311 debug_assert
!(tcx
.dep_graph
1313 .map(|c
| c
.is_green())
1316 let def_id
= self.extract_def_id(tcx
).unwrap();
1317 let _
= tcx
.$
query_name(def_id
);
1328 impl_load_from_cache
!(
1329 TypeckTables
=> typeck_tables_of
,
1330 MirOptimized
=> optimized_mir
,
1331 UnsafetyCheckResult
=> unsafety_check_result
,
1332 BorrowCheck
=> borrowck
,
1333 MirBorrowCheck
=> mir_borrowck
,
1334 MirConstQualif
=> mir_const_qualif
,
1335 SymbolName
=> def_symbol_name
,
1336 ConstIsRvaluePromotableToStatic
=> const_is_rvalue_promotable_to_static
,
1337 CheckMatch
=> check_match
,
1338 TypeOfItem
=> type_of
,
1339 GenericsOfItem
=> generics_of
,
1340 PredicatesOfItem
=> predicates_of
,
1341 UsedTraitImports
=> used_trait_imports
,
1342 CodegenFnAttrs
=> codegen_fn_attrs
,
1343 SpecializationGraph
=> specialization_graph_of
,