|
| 1 | +use std::fmt::Debug; |
1 | 2 | use std::ops::Deref;
|
2 | 3 |
|
| 4 | +use rustc_data_structures::fingerprint::Fingerprint; |
3 | 5 | use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
|
4 | 6 | use rustc_hir::def_id::{DefId, LocalDefId};
|
5 | 7 | use rustc_hir::hir_id::OwnerId;
|
6 | 8 | use rustc_macros::HashStable;
|
7 | 9 | use rustc_query_system::HandleCycleError;
|
8 |
| -use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; |
| 10 | +use rustc_query_system::dep_graph::{DepNodeIndex, DepNodeParams, SerializedDepNodeIndex}; |
| 11 | +use rustc_query_system::ich::StableHashingContext; |
9 | 12 | pub(crate) use rustc_query_system::query::QueryJobId;
|
10 | 13 | use rustc_query_system::query::*;
|
11 | 14 | use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
| 15 | +pub use sealed::IntoQueryParam; |
12 | 16 |
|
| 17 | +use super::erase::EraseType; |
13 | 18 | use crate::dep_graph;
|
14 | 19 | use crate::dep_graph::DepKind;
|
| 20 | +use crate::query::erase::{Erase, restore}; |
15 | 21 | use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
|
16 | 22 | use crate::query::{
|
17 | 23 | DynamicQueries, ExternProviders, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
|
@@ -565,53 +571,77 @@ macro_rules! define_feedable {
|
565 | 571 |
|
566 | 572 | let tcx = self.tcx;
|
567 | 573 | let erased = queries::$name::provided_to_erased(tcx, value);
|
568 |
| - let value = restore::<$V>(erased); |
569 | 574 | let cache = &tcx.query_system.caches.$name;
|
570 | 575 |
|
| 576 | + let name: &'static str = stringify!($name); |
| 577 | + let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; |
571 | 578 | let hasher: Option<fn(&mut StableHashingContext<'_>, &_) -> _> = hash_result!([$($modifiers)*]);
|
572 |
| - match try_get_cached(tcx, cache, &key) { |
573 |
| - Some(old) => { |
574 |
| - let old = restore::<$V>(old); |
575 |
| - if let Some(hasher) = hasher { |
576 |
| - let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx| |
577 |
| - (hasher(&mut hcx, &value), hasher(&mut hcx, &old)) |
578 |
| - ); |
579 |
| - if old_hash != value_hash { |
580 |
| - // We have an inconsistency. This can happen if one of the two |
581 |
| - // results is tainted by errors. In this case, delay a bug to |
582 |
| - // ensure compilation is doomed, and keep the `old` value. |
583 |
| - tcx.dcx().delayed_bug(format!( |
584 |
| - "Trying to feed an already recorded value for query {} key={key:?}:\n\ |
585 |
| - old value: {old:?}\nnew value: {value:?}", |
586 |
| - stringify!($name), |
587 |
| - )); |
588 |
| - } |
589 |
| - } else { |
590 |
| - // The query is `no_hash`, so we have no way to perform a sanity check. |
591 |
| - // If feeding the same value multiple times needs to be supported, |
592 |
| - // the query should not be marked `no_hash`. |
593 |
| - bug!( |
594 |
| - "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}", |
595 |
| - stringify!($name), |
596 |
| - ) |
597 |
| - } |
598 |
| - } |
599 |
| - None => { |
600 |
| - let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::dep_kinds::$name, &key); |
601 |
| - let dep_node_index = tcx.dep_graph.with_feed_task( |
602 |
| - dep_node, |
603 |
| - tcx, |
604 |
| - &value, |
605 |
| - hash_result!([$($modifiers)*]), |
606 |
| - ); |
607 |
| - cache.complete(key, erased, dep_node_index); |
608 |
| - } |
609 |
| - } |
| 579 | + |
| 580 | + $crate::query::plumbing::query_feed_inner( |
| 581 | + tcx, |
| 582 | + name, |
| 583 | + dep_kind, |
| 584 | + hasher, |
| 585 | + cache, |
| 586 | + key, |
| 587 | + erased, |
| 588 | + ); |
610 | 589 | }
|
611 | 590 | })*
|
612 | 591 | }
|
613 | 592 | }
|
614 | 593 |
|
| 594 | +/// Common implementation of query feeding, used by `define_feedable!`. |
| 595 | +pub(crate) fn query_feed_inner<'tcx, Cache, Value>( |
| 596 | + tcx: TyCtxt<'tcx>, |
| 597 | + name: &'static str, |
| 598 | + dep_kind: DepKind, |
| 599 | + hasher: Option<fn(&mut StableHashingContext<'_>, &Value) -> Fingerprint>, |
| 600 | + cache: &Cache, |
| 601 | + key: Cache::Key, |
| 602 | + erased: Erase<Value>, |
| 603 | +) where |
| 604 | + Cache: QueryCache<Value = Erase<Value>>, |
| 605 | + Cache::Key: DepNodeParams<TyCtxt<'tcx>>, |
| 606 | + Value: EraseType + Debug, |
| 607 | +{ |
| 608 | + let value = restore::<Value>(erased); |
| 609 | + |
| 610 | + match try_get_cached(tcx, cache, &key) { |
| 611 | + Some(old) => { |
| 612 | + let old = restore::<Value>(old); |
| 613 | + if let Some(hasher) = hasher { |
| 614 | + let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx |
| 615 | + .with_stable_hashing_context(|mut hcx| { |
| 616 | + (hasher(&mut hcx, &value), hasher(&mut hcx, &old)) |
| 617 | + }); |
| 618 | + if old_hash != value_hash { |
| 619 | + // We have an inconsistency. This can happen if one of the two |
| 620 | + // results is tainted by errors. In this case, delay a bug to |
| 621 | + // ensure compilation is doomed, and keep the `old` value. |
| 622 | + tcx.dcx().delayed_bug(format!( |
| 623 | + "Trying to feed an already recorded value for query {name} key={key:?}:\n\ |
| 624 | + old value: {old:?}\nnew value: {value:?}", |
| 625 | + )); |
| 626 | + } |
| 627 | + } else { |
| 628 | + // The query is `no_hash`, so we have no way to perform a sanity check. |
| 629 | + // If feeding the same value multiple times needs to be supported, |
| 630 | + // the query should not be marked `no_hash`. |
| 631 | + bug!( |
| 632 | + "Trying to feed an already recorded value for query {name} key={key:?}:\n\ |
| 633 | + old value: {old:?}\nnew value: {value:?}", |
| 634 | + ) |
| 635 | + } |
| 636 | + } |
| 637 | + None => { |
| 638 | + let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key); |
| 639 | + let dep_node_index = tcx.dep_graph.with_feed_task(dep_node, tcx, &value, hasher); |
| 640 | + cache.complete(key, erased, dep_node_index); |
| 641 | + } |
| 642 | + } |
| 643 | +} |
| 644 | + |
615 | 645 | // Each of these queries corresponds to a function pointer field in the
|
616 | 646 | // `Providers` struct for requesting a value of that type, and a method
|
617 | 647 | // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
|
@@ -694,10 +724,6 @@ mod sealed {
|
694 | 724 | }
|
695 | 725 | }
|
696 | 726 |
|
697 |
| -pub use sealed::IntoQueryParam; |
698 |
| - |
699 |
| -use super::erase::EraseType; |
700 |
| - |
701 | 727 | #[derive(Copy, Clone, Debug, HashStable)]
|
702 | 728 | pub struct CyclePlaceholder(pub ErrorGuaranteed);
|
703 | 729 |
|
|
0 commit comments