11//! Helper functions that serve as the immediate implementation of
22//! `tcx.$query(..)` and its variations.
33
4- use std:: fmt:: Debug ;
5-
6- use rustc_data_structures:: fingerprint:: Fingerprint ;
74use rustc_query_system:: dep_graph:: { DepKind , DepNodeParams } ;
8- use rustc_query_system:: ich:: StableHashingContext ;
95use rustc_query_system:: query:: { QueryCache , QueryMode , try_get_cached} ;
106use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
117
128use crate :: dep_graph;
139use crate :: query:: IntoQueryParam ;
1410use crate :: query:: erase:: { self , Erasable , Erased } ;
11+ use crate :: query:: plumbing:: QueryVTable ;
1512use crate :: ty:: TyCtxt ;
1613
1714/// Shared implementation of `tcx.$query(..)` and `tcx.at(span).$query(..)`
@@ -84,35 +81,38 @@ where
8481}
8582
8683/// Common implementation of query feeding, used by `define_feedable!`.
87- pub ( crate ) fn query_feed < ' tcx , Cache , Value > (
84+ pub ( crate ) fn query_feed < ' tcx , Cache > (
8885 tcx : TyCtxt < ' tcx > ,
8986 dep_kind : DepKind ,
90- hasher : Option < fn ( & mut StableHashingContext < ' _ > , & Value ) -> Fingerprint > ,
87+ query_vtable : & QueryVTable < ' tcx , Cache > ,
9188 cache : & Cache ,
9289 key : Cache :: Key ,
93- erased : Erased < Value > ,
90+ value : Cache :: Value ,
9491) where
95- Cache : QueryCache < Value = Erased < Value > > ,
92+ Cache : QueryCache ,
9693 Cache :: Key : DepNodeParams < TyCtxt < ' tcx > > ,
97- Value : Erasable + Debug ,
9894{
99- let value = erase :: restore_val :: < Value > ( erased ) ;
95+ let format_value = query_vtable . format_value ;
10096
97+ // Check whether the in-memory cache already has a value for this key.
10198 match try_get_cached ( tcx, cache, & key) {
10299 Some ( old) => {
103- let old = erase:: restore_val :: < Value > ( old) ;
104- if let Some ( hasher) = hasher {
105- let ( value_hash, old_hash) : ( Fingerprint , Fingerprint ) = tcx
106- . with_stable_hashing_context ( |mut hcx| {
107- ( hasher ( & mut hcx, & value) , hasher ( & mut hcx, & old) )
108- } ) ;
100+ // The query already has a cached value for this key.
101+ // That's OK if both values are the same, i.e. they have the same hash,
102+ // so now we check their hashes.
103+ if let Some ( hasher_fn) = query_vtable. hash_result {
104+ let ( old_hash, value_hash) = tcx. with_stable_hashing_context ( |ref mut hcx| {
105+ ( hasher_fn ( hcx, & old) , hasher_fn ( hcx, & value) )
106+ } ) ;
109107 if old_hash != value_hash {
110108 // We have an inconsistency. This can happen if one of the two
111109 // results is tainted by errors. In this case, delay a bug to
112110 // ensure compilation is doomed, and keep the `old` value.
113111 tcx. dcx ( ) . delayed_bug ( format ! (
114112 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n \
115- old value: {old:?}\n new value: {value:?}",
113+ old value: {old}\n new value: {value}",
114+ old = format_value( & old) ,
115+ value = format_value( & value) ,
116116 ) ) ;
117117 }
118118 } else {
@@ -121,14 +121,24 @@ pub(crate) fn query_feed<'tcx, Cache, Value>(
121121 // the query should not be marked `no_hash`.
122122 bug ! (
123123 "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n \
124- old value: {old:?}\n new value: {value:?}",
124+ old value: {old}\n new value: {value}",
125+ old = format_value( & old) ,
126+ value = format_value( & value) ,
125127 )
126128 }
127129 }
128130 None => {
131+ // There is no cached value for this key, so feed the query by
132+ // adding the provided value to the cache.
129133 let dep_node = dep_graph:: DepNode :: construct ( tcx, dep_kind, & key) ;
130- let dep_node_index = tcx. dep_graph . with_feed_task ( dep_node, tcx, & value, hasher) ;
131- cache. complete ( key, erased, dep_node_index) ;
134+ let dep_node_index = tcx. dep_graph . with_feed_task (
135+ dep_node,
136+ tcx,
137+ & value,
138+ query_vtable. hash_result ,
139+ query_vtable. format_value ,
140+ ) ;
141+ cache. complete ( key, value, dep_node_index) ;
132142 }
133143 }
134144}
0 commit comments