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 ty::maps::config::QueryDescription;
19 use ty::maps::job::{QueryResult, QueryInfo};
22 use rustc_data_structures::fx::{FxHashMap};
23 use rustc_data_structures::sync::LockGuard;
24 use std::marker::PhantomData;
27 pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> {
28 phantom: PhantomData<(D, &'tcx ())>,
29 pub(super) map: FxHashMap<D::Key, QueryResult<'tcx, QueryValue<D::Value>>>,
32 pub(super) struct QueryValue<T> {
34 pub(super) index: DepNodeIndex,
37 impl<T> QueryValue<T> {
38 pub(super) fn new(value: T,
39 dep_node_index: DepNodeIndex)
43 index: dep_node_index,
48 impl<'tcx, M: QueryDescription<'tcx>> QueryMap<'tcx, M> {
49 pub(super) fn new() -> QueryMap<'tcx, M> {
57 pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
58 fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
59 -> LockGuard<'a, QueryMap<'tcx, Self>>;
63 pub(super) struct CycleError<'tcx> {
64 pub(super) span: Span,
65 pub(super) cycle: Vec<QueryInfo<'tcx>>,
68 /// The result of `try_get_lock`
69 pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
70 /// The query is not yet started. Contains a guard to the map eventually used to start it.
71 NotYetStarted(LockGuard<'a, QueryMap<'tcx, D>>),
73 /// The query was already completed.
74 /// Returns the result of the query and its dep node index
75 /// if it succeeded or a cycle error if it failed
76 JobCompleted(Result<(T, DepNodeIndex), CycleError<'tcx>>),
79 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
80 pub(super) fn report_cycle(self, CycleError { span, cycle: stack }: CycleError)
81 -> DiagnosticBuilder<'a>
83 assert!(!stack.is_empty());
85 // Disable naming impls with types in this path, since that
86 // sometimes cycles itself, leading to extra cycle errors.
87 // (And cycle errors around impls tend to occur during the
88 // collect/coherence phases anyhow.)
89 item_path::with_forced_impl_filename_line(|| {
90 let span = self.sess.codemap().def_span(span);
92 struct_span_err!(self.sess, span, E0391,
93 "cyclic dependency detected");
94 err.span_label(span, "cyclic reference");
96 err.span_note(self.sess.codemap().def_span(stack[0].span),
97 &format!("the cycle begins when {}...", stack[0].query.describe(self)));
99 for &QueryInfo { span, ref query, .. } in &stack[1..] {
100 err.span_note(self.sess.codemap().def_span(span),
101 &format!("...which then requires {}...", query.describe(self)));
104 err.note(&format!("...which then again requires {}, completing the cycle.",
105 stack[0].query.describe(self)));
111 /// Try to read a node index for the node dep_node.
112 /// A node will have an index, when it's already been marked green, or when we can mark it
113 /// green. This function will mark the current task as a reader of the specified node, when
114 /// the a node index can be found for that node.
115 pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option<DepNodeIndex> {
116 match self.dep_graph.node_color(dep_node) {
117 Some(DepNodeColor::Green(dep_node_index)) => {
118 self.dep_graph.read_index(dep_node_index);
121 Some(DepNodeColor::Red) => {
125 // try_mark_green (called below) will panic when full incremental
126 // compilation is disabled. If that's the case, we can't try to mark nodes
127 // as green anyway, so we can safely return None here.
128 if !self.dep_graph.is_fully_enabled() {
131 match self.dep_graph.try_mark_green(self.global_tcx(), &dep_node) {
132 Some(dep_node_index) => {
133 debug_assert!(self.dep_graph.is_green(&dep_node));
134 self.dep_graph.read_index(dep_node_index);
146 // If enabled, send a message to the profile-queries thread
147 macro_rules! profq_msg {
148 ($tcx:expr, $msg:expr) => {
149 if cfg!(debug_assertions) {
150 if $tcx.sess.profile_queries() {
151 profq_msg($tcx.sess, $msg)
157 // If enabled, format a key using its debug string, which can be
158 // expensive to compute (in terms of time).
159 macro_rules! profq_key {
160 ($tcx:expr, $key:expr) => {
161 if cfg!(debug_assertions) {
162 if $tcx.sess.profile_queries_and_keys() {
163 Some(format!("{:?}", $key))
169 macro_rules! handle_cycle_error {
170 ([][$this: expr]) => {{
171 Value::from_cycle_error($this.global_tcx())
173 ([fatal_cycle$(, $modifiers:ident)*][$this:expr]) => {{
174 $this.tcx.sess.abort_if_errors();
177 ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => {
178 handle_cycle_error!([$($modifiers),*][$($args)*])
182 macro_rules! define_maps {
185 [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
187 use dep_graph::DepNodeIndex;
189 use errors::Diagnostic;
190 use errors::FatalError;
191 use rustc_data_structures::sync::{Lock, LockGuard};
192 use rustc_data_structures::OnDrop;
196 input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
199 impl<$tcx> Maps<$tcx> {
200 pub fn new(providers: IndexVec<CrateNum, Providers<$tcx>>)
204 $($name: Lock::new(QueryMap::new())),*
210 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
211 pub enum Query<$tcx> {
212 $($(#[$attr])* $name($K)),*
216 #[derive(Clone, Debug, PartialEq, Eq)]
218 $($name(Option<String>)),*
221 impl<$tcx> Query<$tcx> {
222 pub fn describe(&self, tcx: TyCtxt) -> String {
223 let (r, name) = match *self {
224 $(Query::$name(key) => {
225 (queries::$name::describe(tcx, key), stringify!($name))
228 if tcx.sess.verbose() {
229 format!("{} [{}]", r, name)
237 use std::marker::PhantomData;
239 $(#[allow(bad_style)]
240 pub struct $name<$tcx> {
241 data: PhantomData<&$tcx ()>
245 $(impl<$tcx> QueryConfig for queries::$name<$tcx> {
250 impl<$tcx> GetCacheInternal<$tcx> for queries::$name<$tcx> {
251 fn get_cache_internal<'a>(tcx: TyCtxt<'a, $tcx, $tcx>)
252 -> LockGuard<'a, QueryMap<$tcx, Self>> {
253 tcx.maps.$name.borrow()
257 impl<'a, $tcx, 'lcx> queries::$name<$tcx> {
260 fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode {
261 use dep_graph::DepConstructor::*;
263 DepNode::new(tcx, $node(*key))
266 /// Either get the lock of the query map, allowing us to
267 /// start executing the query, or it returns with the result of the query.
268 /// If the query already executed and panicked, this will fatal error / silently panic
270 tcx: TyCtxt<'a, $tcx, 'lcx>,
273 ) -> TryGetLock<'a, $tcx, $V, Self>
276 let lock = tcx.maps.$name.borrow_mut();
277 let job = if let Some(value) = lock.map.get(key) {
279 QueryResult::Started(ref job) => Some(job.clone()),
280 QueryResult::Complete(ref value) => {
281 profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
282 let result = Ok(((&value.value).clone(), value.index));
283 return TryGetLock::JobCompleted(result);
285 QueryResult::Poisoned => FatalError.raise(),
290 let job = if let Some(job) = job {
293 return TryGetLock::NotYetStarted(lock);
297 // This just matches the behavior of `try_get_with` so the span when
298 // we await matches the span we would use when executing.
299 // See the FIXME there.
300 if span == DUMMY_SP && stringify!($name) != "def_span" {
301 span = key.default_span(tcx);
304 if let Err(cycle) = job.await(tcx, span) {
305 return TryGetLock::JobCompleted(Err(cycle));
310 fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
313 -> Result<$V, CycleError<$tcx>>
315 debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
321 ProfileQueriesMsg::QueryBegin(
323 QueryMsg::$name(profq_key!(tcx, key))
327 /// Get the lock used to start the query or
328 /// return the result of the completed query
329 macro_rules! get_lock_or_return {
331 match Self::try_get_lock(tcx, span, &key) {
332 TryGetLock::NotYetStarted(lock) => lock,
333 TryGetLock::JobCompleted(result) => {
334 return result.map(|(v, index)| {
335 tcx.dep_graph.read_index(index);
343 let mut lock = get_lock_or_return!();
345 // FIXME(eddyb) Get more valid Span's on queries.
346 // def_span guard is necessary to prevent a recursive loop,
347 // default_span calls def_span query internally.
348 if span == DUMMY_SP && stringify!($name) != "def_span" {
349 // This might deadlock if we hold the map lock since we might be
350 // waiting for the def_span query and switch to some other fiber
351 // So we drop the lock here and reacquire it
353 span = key.default_span(tcx);
354 lock = get_lock_or_return!();
357 // Fast path for when incr. comp. is off. `to_dep_node` is
358 // expensive for some DepKinds.
359 if !tcx.dep_graph.is_fully_enabled() {
360 let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
361 return Self::force_with_lock(tcx, key, span, lock, null_dep_node)
365 let dep_node = Self::to_dep_node(tcx, &key);
367 if dep_node.kind.is_anon() {
368 profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
370 let res = Self::start_job(tcx, span, key, lock, |tcx| {
371 tcx.dep_graph.with_anon_task(dep_node.kind, || {
372 Self::compute_result(tcx.global_tcx(), key)
376 profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
377 let (((result, dep_node_index), diagnostics), job) = res;
379 tcx.dep_graph.read_index(dep_node_index);
381 tcx.on_disk_query_result_cache
382 .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
384 let value = QueryValue::new(Clone::clone(&result), dep_node_index);
390 .insert(key, QueryResult::Complete(value));
392 job.signal_complete();
397 if !dep_node.kind.is_input() {
398 // try_mark_green_and_read may force queries. So we must drop our lock here
400 if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) {
401 profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
402 return Self::load_from_disk_and_cache_in_memory(tcx,
408 lock = get_lock_or_return!();
411 match Self::force_with_lock(tcx, key, span, lock, dep_node) {
412 Ok((result, dep_node_index)) => {
413 tcx.dep_graph.read_index(dep_node_index);
420 /// Ensure that either this query has all green inputs or been executed.
421 /// Executing query::ensure(D) is considered a read of the dep-node D.
423 /// This function is particularly useful when executing passes for their
424 /// side-effects -- e.g., in order to report errors for erroneous programs.
426 /// Note: The optimization is only available during incr. comp.
427 pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () {
428 let dep_node = Self::to_dep_node(tcx, &key);
430 // Ensuring an "input" or anonymous query makes no sense
431 assert!(!dep_node.kind.is_anon());
432 assert!(!dep_node.kind.is_input());
433 if tcx.try_mark_green_and_read(&dep_node).is_none() {
434 // A None return from `try_mark_green_and_read` means that this is either
435 // a new dep node or that the dep node has already been marked red.
436 // Either way, we can't call `dep_graph.read()` as we don't have the
437 // DepNodeIndex. We must invoke the query itself. The performance cost
438 // this introduces should be negligible as we'll immediately hit the
439 // in-memory cache, or another query down the line will.
440 let _ = tcx.$name(key);
444 /// Creates a job for the query and updates the query map indicating that it started.
445 /// Then it changes ImplicitCtxt to point to the new query job while it executes.
446 /// If the query panics, this updates the query map to indicate so.
447 fn start_job<F, R>(tcx: TyCtxt<'_, $tcx, 'lcx>,
450 mut map: LockGuard<'_, QueryMap<$tcx, Self>>,
452 -> Result<((R, Vec<Diagnostic>), Lrc<QueryJob<$tcx>>), CycleError<$tcx>>
453 where F: for<'b> FnOnce(TyCtxt<'b, $tcx, 'lcx>) -> R
455 let query = Query::$name(Clone::clone(&key));
457 let entry = QueryInfo {
462 // The TyCtxt stored in TLS has the same global interner lifetime
463 // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
464 // when accessing the ImplicitCtxt
465 let (r, job) = ty::tls::with_related_context(tcx, move |icx| {
466 let job = Lrc::new(QueryJob::new(entry, icx.query.clone()));
468 // Store the job in the query map and drop the lock to allow
470 map.map.entry(key).or_insert(QueryResult::Started(job.clone()));
474 let on_drop = OnDrop(|| {
475 // Poison the query so jobs waiting on it panic
480 .insert(key, QueryResult::Poisoned);
481 // Also signal the completion of the job, so waiters
482 // will continue execution
483 job.signal_complete();
486 // Update the ImplicitCtxt to point to our new query job
487 let icx = ty::tls::ImplicitCtxt {
489 query: Some(job.clone()),
492 // Use the ImplicitCtxt while we execute the query
493 let r = ty::tls::enter_context(&icx, |icx| {
497 mem::forget(on_drop);
505 // Extract the diagnostic from the job
506 let diagnostics: Vec<_> = mem::replace(&mut *job.diagnostics.lock(), Vec::new());
508 Ok(((r, diagnostics), job))
511 fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
512 let provider = tcx.maps.providers[key.map_crate()].$name;
513 provider(tcx.global_tcx(), key)
516 fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
519 dep_node_index: DepNodeIndex,
521 -> Result<$V, CycleError<$tcx>>
523 // Note this function can be called concurrently from the same query
524 // We must ensure that this is handled correctly
526 debug_assert!(tcx.dep_graph.is_green(dep_node));
528 // First we try to load the result from the on-disk cache
529 let result = if Self::cache_on_disk(key) &&
530 tcx.sess.opts.debugging_opts.incremental_queries {
531 let prev_dep_node_index =
532 tcx.dep_graph.prev_dep_node_index_of(dep_node);
533 let result = Self::try_load_from_disk(tcx.global_tcx(),
534 prev_dep_node_index);
536 // We always expect to find a cached result for things that
537 // can be forced from DepNode.
538 debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
540 "Missing on-disk cache entry for {:?}",
544 // Some things are never cached on disk.
548 let (result, job) = if let Some(result) = result {
551 // We could not load a result from the on-disk cache, so
554 // The diagnostics for this query have already been
555 // promoted to the current session during
556 // try_mark_green(), so we can ignore them here.
557 let ((result, _), job) = Self::start_job(tcx,
560 tcx.maps.$name.borrow_mut(),
562 // The dep-graph for this computation is already in
564 tcx.dep_graph.with_ignore(|| {
565 Self::compute_result(tcx, key)
571 // If -Zincremental-verify-ich is specified, re-hash results from
572 // the cache and make sure that they have the expected fingerprint.
573 if tcx.sess.opts.debugging_opts.incremental_verify_ich {
574 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
575 use ich::Fingerprint;
577 assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) ==
578 tcx.dep_graph.prev_fingerprint_of(dep_node),
579 "Fingerprint for green query instance not loaded \
580 from cache: {:?}", dep_node);
582 debug!("BEGIN verify_ich({:?})", dep_node);
583 let mut hcx = tcx.create_stable_hashing_context();
584 let mut hasher = StableHasher::new();
586 result.hash_stable(&mut hcx, &mut hasher);
588 let new_hash: Fingerprint = hasher.finish();
589 debug!("END verify_ich({:?})", dep_node);
591 let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index);
593 assert!(new_hash == old_hash, "Found unstable fingerprints \
594 for {:?}", dep_node);
597 if tcx.sess.opts.debugging_opts.query_dep_graph {
598 tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
601 let value = QueryValue::new(Clone::clone(&result), dep_node_index);
607 .insert(key, QueryResult::Complete(value));
609 job.map(|j| j.signal_complete());
615 fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
619 -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
620 // We may be concurrently trying both execute and force a query
621 // Ensure that only one of them runs the query
622 let lock = match Self::try_get_lock(tcx, span, &key) {
623 TryGetLock::NotYetStarted(lock) => lock,
624 TryGetLock::JobCompleted(result) => return result,
626 Self::force_with_lock(tcx,
633 fn force_with_lock(tcx: TyCtxt<'a, $tcx, 'lcx>,
636 map: LockGuard<'_, QueryMap<$tcx, Self>>,
638 -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
639 debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node));
641 profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
642 let res = Self::start_job(tcx,
647 if dep_node.kind.is_eval_always() {
648 tcx.dep_graph.with_eval_always_task(dep_node,
651 Self::compute_result)
653 tcx.dep_graph.with_task(dep_node,
656 Self::compute_result)
659 profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
661 let (((result, dep_node_index), diagnostics), job) = res;
663 if tcx.sess.opts.debugging_opts.query_dep_graph {
664 tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false);
667 if dep_node.kind != ::dep_graph::DepKind::Null {
668 tcx.on_disk_query_result_cache
669 .store_diagnostics(dep_node_index, diagnostics);
672 let value = QueryValue::new(Clone::clone(&result), dep_node_index);
678 .insert(key, QueryResult::Complete(value));
680 let job: Lrc<QueryJob> = job;
682 job.signal_complete();
684 Ok((result, dep_node_index))
687 pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
688 -> Result<$V, DiagnosticBuilder<'a>> {
689 match Self::try_get_with(tcx, span, key) {
691 Err(e) => Err(tcx.report_cycle(e)),
696 #[derive(Copy, Clone)]
697 pub struct TyCtxtAt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
698 pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
702 impl<'a, 'gcx, 'tcx> Deref for TyCtxtAt<'a, 'gcx, 'tcx> {
703 type Target = TyCtxt<'a, 'gcx, 'tcx>;
704 fn deref(&self) -> &Self::Target {
709 impl<'a, $tcx, 'lcx> TyCtxt<'a, $tcx, 'lcx> {
710 /// Return a transparent wrapper for `TyCtxt` which uses
711 /// `span` as the location of queries performed through it.
712 pub fn at(self, span: Span) -> TyCtxtAt<'a, $tcx, 'lcx> {
720 pub fn $name(self, key: $K) -> $V {
721 self.at(DUMMY_SP).$name(key)
725 impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
727 pub fn $name(self, key: $K) -> $V {
728 queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
730 handle_cycle_error!([$($modifiers)*][self])
735 define_provider_struct! {
737 input: ($(([$($modifiers)*] [$name] [$K] [$V]))*)
740 impl<$tcx> Copy for Providers<$tcx> {}
741 impl<$tcx> Clone for Providers<$tcx> {
742 fn clone(&self) -> Self { *self }
747 macro_rules! define_map_struct {
749 input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
750 pub struct Maps<$tcx> {
751 providers: IndexVec<CrateNum, Providers<$tcx>>,
752 $($(#[$attr])* $name: Lock<QueryMap<$tcx, queries::$name<$tcx>>>,)*
757 macro_rules! define_provider_struct {
759 input: ($(([$($modifiers:tt)*] [$name:ident] [$K:ty] [$R:ty]))*)) => {
760 pub struct Providers<$tcx> {
761 $(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $R,)*
764 impl<$tcx> Default for Providers<$tcx> {
765 fn default() -> Self {
766 $(fn $name<'a, $tcx>(_: TyCtxt<'a, $tcx, $tcx>, key: $K) -> $R {
767 bug!("tcx.maps.{}({:?}) unsupported by its crate",
768 stringify!($name), key);
770 Providers { $($name),* }
777 /// The red/green evaluation system will try to mark a specific DepNode in the
778 /// dependency graph as green by recursively trying to mark the dependencies of
779 /// that DepNode as green. While doing so, it will sometimes encounter a DepNode
780 /// where we don't know if it is red or green and we therefore actually have
781 /// to recompute its value in order to find out. Since the only piece of
782 /// information that we have at that point is the DepNode we are trying to
783 /// re-evaluate, we need some way to re-run a query from just that. This is what
784 /// `force_from_dep_node()` implements.
786 /// In the general case, a DepNode consists of a DepKind and an opaque
787 /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
788 /// is usually constructed by computing a stable hash of the query-key that the
789 /// DepNode corresponds to. Consequently, it is not in general possible to go
790 /// back from hash to query-key (since hash functions are not reversible). For
791 /// this reason `force_from_dep_node()` is expected to fail from time to time
792 /// because we just cannot find out, from the DepNode alone, what the
793 /// corresponding query-key is and therefore cannot re-run the query.
795 /// The system deals with this case letting `try_mark_green` fail which forces
796 /// the root query to be re-evaluated.
798 /// Now, if force_from_dep_node() would always fail, it would be pretty useless.
799 /// Fortunately, we can use some contextual information that will allow us to
800 /// reconstruct query-keys for certain kinds of DepNodes. In particular, we
801 /// enforce by construction that the GUID/fingerprint of certain DepNodes is a
802 /// valid DefPathHash. Since we also always build a huge table that maps every
803 /// DefPathHash in the current codebase to the corresponding DefId, we have
804 /// everything we need to re-run the query.
806 /// Take the `mir_validated` query as an example. Like many other queries, it
807 /// just has a single parameter: the DefId of the item it will compute the
808 /// validated MIR for. Now, when we call `force_from_dep_node()` on a dep-node
809 /// with kind `MirValidated`, we know that the GUID/fingerprint of the dep-node
810 /// is actually a DefPathHash, and can therefore just look up the corresponding
811 /// DefId in `tcx.def_path_hash_to_def_id`.
813 /// When you implement a new query, it will likely have a corresponding new
814 /// DepKind, and you'll have to support it here in `force_from_dep_node()`. As
815 /// a rule of thumb, if your query takes a DefId or DefIndex as sole parameter,
816 /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
817 /// add it to the "We don't have enough information to reconstruct..." group in
819 pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
822 use ty::maps::keys::Key;
823 use hir::def_id::LOCAL_CRATE;
825 // We must avoid ever having to call force_from_dep_node() for a
826 // DepNode::CodegenUnit:
827 // Since we cannot reconstruct the query key of a DepNode::CodegenUnit, we
828 // would always end up having to evaluate the first caller of the
829 // `codegen_unit` query that *is* reconstructible. This might very well be
830 // the `compile_codegen_unit` query, thus re-translating the whole CGU just
831 // to re-trigger calling the `codegen_unit` query with the right key. At
832 // that point we would already have re-done all the work we are trying to
833 // avoid doing in the first place.
834 // The solution is simple: Just explicitly call the `codegen_unit` query for
835 // each CGU, right after partitioning. This way `try_mark_green` will always
836 // hit the cache instead of having to go through `force_from_dep_node`.
837 // This assertion makes sure, we actually keep applying the solution above.
838 debug_assert!(dep_node.kind != DepKind::CodegenUnit,
839 "calling force_from_dep_node() on DepKind::CodegenUnit");
841 if !dep_node.kind.can_reconstruct_query_key() {
845 macro_rules! def_id {
847 if let Some(def_id) = dep_node.extract_def_id(tcx) {
850 // return from the whole function
857 () => { (def_id!()).krate }
861 ($query:ident, $key:expr) => {
863 use $crate::util::common::{ProfileQueriesMsg, profq_msg};
865 // FIXME(eddyb) Get more valid Span's on queries.
866 // def_span guard is necessary to prevent a recursive loop,
867 // default_span calls def_span query internally.
868 let span = if stringify!($query) != "def_span" {
869 $key.default_span(tcx)
871 ::syntax_pos::DUMMY_SP
875 ProfileQueriesMsg::QueryBegin(
877 ::ty::maps::QueryMsg::$query(profq_key!(tcx, $key))
881 match ::ty::maps::queries::$query::force(tcx, $key, span, *dep_node) {
884 tcx.report_cycle(e).emit();
891 // FIXME(#45015): We should try move this boilerplate code into a macro
893 match dep_node.kind {
894 // These are inputs that are expected to be pre-allocated and that
895 // should therefore always be red or green already
896 DepKind::AllLocalTraitImpls |
898 DepKind::CrateMetadata |
902 // This are anonymous nodes
903 DepKind::TraitSelect |
905 // We don't have enough information to reconstruct the query key of
913 DepKind::InstanceSymbolName |
915 DepKind::BorrowCheckKrate |
916 DepKind::Specializes |
917 DepKind::ImplementationsOfTrait |
918 DepKind::TypeParamPredicates |
919 DepKind::CodegenUnit |
920 DepKind::CompileCodegenUnit |
921 DepKind::FulfillObligation |
922 DepKind::VtableMethods |
923 DepKind::EraseRegionsTy |
924 DepKind::NormalizeProjectionTy |
925 DepKind::NormalizeTyAfterErasingRegions |
926 DepKind::DropckOutlives |
927 DepKind::SubstituteNormalizeAndTestPredicates |
928 DepKind::InstanceDefSizeEstimate |
930 // This one should never occur in this context
932 bug!("force_from_dep_node() - Encountered {:?}", dep_node)
935 // These are not queries
936 DepKind::CoherenceCheckTrait |
937 DepKind::ItemVarianceConstraints => {
941 DepKind::RegionScopeTree => { force!(region_scope_tree, def_id!()); }
943 DepKind::Coherence => { force!(crate_inherent_impls, LOCAL_CRATE); }
944 DepKind::CoherenceInherentImplOverlapCheck => {
945 force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
947 DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
948 DepKind::MirBuilt => { force!(mir_built, def_id!()); }
949 DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
950 DepKind::MirConst => { force!(mir_const, def_id!()); }
951 DepKind::MirValidated => { force!(mir_validated, def_id!()); }
952 DepKind::MirOptimized => { force!(optimized_mir, def_id!()); }
954 DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
955 DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
956 DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
957 DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
958 DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
959 DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
960 DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
961 DepKind::AssociatedItems => { force!(associated_item, def_id!()); }
962 DepKind::TypeOfItem => { force!(type_of, def_id!()); }
963 DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
964 DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
965 DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
966 DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
967 DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
968 DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
969 DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
970 DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
971 DepKind::FnSignature => { force!(fn_sig, def_id!()); }
972 DepKind::CoerceUnsizedInfo => { force!(coerce_unsized_info, def_id!()); }
973 DepKind::ItemVariances => { force!(variances_of, def_id!()); }
974 DepKind::IsConstFn => { force!(is_const_fn, def_id!()); }
975 DepKind::IsForeignItem => { force!(is_foreign_item, def_id!()); }
976 DepKind::SizedConstraint => { force!(adt_sized_constraint, def_id!()); }
977 DepKind::DtorckConstraint => { force!(adt_dtorck_constraint, def_id!()); }
978 DepKind::AdtDestructor => { force!(adt_destructor, def_id!()); }
979 DepKind::AssociatedItemDefIds => { force!(associated_item_def_ids, def_id!()); }
980 DepKind::InherentImpls => { force!(inherent_impls, def_id!()); }
981 DepKind::TypeckBodiesKrate => { force!(typeck_item_bodies, LOCAL_CRATE); }
982 DepKind::TypeckTables => { force!(typeck_tables_of, def_id!()); }
983 DepKind::UsedTraitImports => { force!(used_trait_imports, def_id!()); }
984 DepKind::HasTypeckTables => { force!(has_typeck_tables, def_id!()); }
985 DepKind::SymbolName => { force!(def_symbol_name, def_id!()); }
986 DepKind::SpecializationGraph => { force!(specialization_graph_of, def_id!()); }
987 DepKind::ObjectSafety => { force!(is_object_safe, def_id!()); }
988 DepKind::TraitImpls => { force!(trait_impls_of, def_id!()); }
989 DepKind::CheckMatch => { force!(check_match, def_id!()); }
991 DepKind::ParamEnv => { force!(param_env, def_id!()); }
992 DepKind::DescribeDef => { force!(describe_def, def_id!()); }
993 DepKind::DefSpan => { force!(def_span, def_id!()); }
994 DepKind::LookupStability => { force!(lookup_stability, def_id!()); }
995 DepKind::LookupDeprecationEntry => {
996 force!(lookup_deprecation_entry, def_id!());
998 DepKind::ItemBodyNestedBodies => { force!(item_body_nested_bodies, def_id!()); }
999 DepKind::ConstIsRvaluePromotableToStatic => {
1000 force!(const_is_rvalue_promotable_to_static, def_id!());
1002 DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
1003 DepKind::ImplParent => { force!(impl_parent, def_id!()); }
1004 DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
1005 DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
1006 DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
1007 DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
1008 DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }
1009 DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
1010 DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
1011 DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
1012 DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); }
1013 DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
1014 DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
1015 DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); }
1016 DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
1017 DepKind::ModuleExports => { force!(module_exports, def_id!()); }
1018 DepKind::IsSanitizerRuntime => { force!(is_sanitizer_runtime, krate!()); }
1019 DepKind::IsProfilerRuntime => { force!(is_profiler_runtime, krate!()); }
1020 DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
1021 DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
1022 DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
1023 DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); }
1024 DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
1025 DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
1026 DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
1027 DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
1028 DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
1029 DepKind::DeriveRegistrarFn => { force!(derive_registrar_fn, krate!()); }
1030 DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
1031 DepKind::CrateHash => { force!(crate_hash, krate!()); }
1032 DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); }
1033 DepKind::ExtraFileName => { force!(extra_filename, krate!()); }
1035 DepKind::AllTraitImplementations => {
1036 force!(all_trait_implementations, krate!());
1039 DepKind::DllimportForeignItems => {
1040 force!(dllimport_foreign_items, krate!());
1042 DepKind::IsDllimportForeignItem => {
1043 force!(is_dllimport_foreign_item, def_id!());
1045 DepKind::IsStaticallyIncludedForeignItem => {
1046 force!(is_statically_included_foreign_item, def_id!());
1048 DepKind::NativeLibraryKind => { force!(native_library_kind, def_id!()); }
1049 DepKind::LinkArgs => { force!(link_args, LOCAL_CRATE); }
1051 DepKind::ResolveLifetimes => { force!(resolve_lifetimes, krate!()); }
1052 DepKind::NamedRegion => { force!(named_region_map, def_id!().index); }
1053 DepKind::IsLateBound => { force!(is_late_bound_map, def_id!().index); }
1054 DepKind::ObjectLifetimeDefaults => {
1055 force!(object_lifetime_defaults_map, def_id!().index);
1058 DepKind::Visibility => { force!(visibility, def_id!()); }
1059 DepKind::DepKind => { force!(dep_kind, krate!()); }
1060 DepKind::CrateName => { force!(crate_name, krate!()); }
1061 DepKind::ItemChildren => { force!(item_children, def_id!()); }
1062 DepKind::ExternModStmtCnum => { force!(extern_mod_stmt_cnum, def_id!()); }
1063 DepKind::GetLangItems => { force!(get_lang_items, LOCAL_CRATE); }
1064 DepKind::DefinedLangItems => { force!(defined_lang_items, krate!()); }
1065 DepKind::MissingLangItems => { force!(missing_lang_items, krate!()); }
1066 DepKind::ExternConstBody => { force!(extern_const_body, def_id!()); }
1067 DepKind::VisibleParentMap => { force!(visible_parent_map, LOCAL_CRATE); }
1068 DepKind::MissingExternCrateItem => {
1069 force!(missing_extern_crate_item, krate!());
1071 DepKind::UsedCrateSource => { force!(used_crate_source, krate!()); }
1072 DepKind::PostorderCnums => { force!(postorder_cnums, LOCAL_CRATE); }
1074 DepKind::Freevars => { force!(freevars, def_id!()); }
1075 DepKind::MaybeUnusedTraitImport => {
1076 force!(maybe_unused_trait_import, def_id!());
1078 DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
1079 DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
1080 DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
1081 DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
1082 DepKind::CollectAndPartitionTranslationItems => {
1083 force!(collect_and_partition_translation_items, LOCAL_CRATE);
1085 DepKind::IsTranslatedItem => { force!(is_translated_item, def_id!()); }
1086 DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
1088 DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
1090 DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
1091 DepKind::Features => { force!(features_query, LOCAL_CRATE); }
1093 DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
1094 DepKind::WasmCustomSections => { force!(wasm_custom_sections, krate!()); }
1095 DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
1096 DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
1103 // FIXME(#45015): Another piece of boilerplate code that could be generated in
1104 // a combined define_dep_nodes!()/define_maps!() macro.
1105 macro_rules! impl_load_from_cache {
1106 ($($dep_kind:ident => $query_name:ident,)*) => {
1108 // Check whether the query invocation corresponding to the given
1109 // DepNode is eligible for on-disk-caching.
1110 pub fn cache_on_disk(&self, tcx: TyCtxt) -> bool {
1111 use ty::maps::queries;
1112 use ty::maps::QueryDescription;
1115 $(DepKind::$dep_kind => {
1116 let def_id = self.extract_def_id(tcx).unwrap();
1117 queries::$query_name::cache_on_disk(def_id)
1123 // This is method will execute the query corresponding to the given
1124 // DepNode. It is only expected to work for DepNodes where the
1125 // above `cache_on_disk` methods returns true.
1126 // Also, as a sanity check, it expects that the corresponding query
1127 // invocation has been marked as green already.
1128 pub fn load_from_on_disk_cache(&self, tcx: TyCtxt) {
1130 $(DepKind::$dep_kind => {
1131 debug_assert!(tcx.dep_graph
1133 .map(|c| c.is_green())
1136 let def_id = self.extract_def_id(tcx).unwrap();
1137 let _ = tcx.$query_name(def_id);
1148 impl_load_from_cache!(
1149 TypeckTables => typeck_tables_of,
1150 MirOptimized => optimized_mir,
1151 UnsafetyCheckResult => unsafety_check_result,
1152 BorrowCheck => borrowck,
1153 MirBorrowCheck => mir_borrowck,
1154 MirConstQualif => mir_const_qualif,
1155 SymbolName => def_symbol_name,
1156 ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
1157 CheckMatch => check_match,
1158 TypeOfItem => type_of,
1159 GenericsOfItem => generics_of,
1160 PredicatesOfItem => predicates_of,
1161 UsedTraitImports => used_trait_imports,
1162 TransFnAttrs => trans_fn_attrs,
1163 SpecializationGraph => specialization_graph_of,