@@ -66,6 +66,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
66
66
use rustc_hir:: definitions:: DefPathHash ;
67
67
use rustc_hir:: HirId ;
68
68
use rustc_span:: symbol:: Symbol ;
69
+ use rustc_span:: DUMMY_SP ;
69
70
use std:: hash:: Hash ;
70
71
71
72
pub use rustc_query_system:: dep_graph:: { DepContext , DepNodeParams } ;
@@ -95,6 +96,50 @@ pub struct DepKindStruct {
95
96
// can be made a specialized associated const.
96
97
can_reconstruct_query_key : fn ( ) -> bool ,
97
98
99
+ /// The red/green evaluation system will try to mark a specific DepNode in the
100
+ /// dependency graph as green by recursively trying to mark the dependencies of
101
+ /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
102
+ /// where we don't know if it is red or green and we therefore actually have
103
+ /// to recompute its value in order to find out. Since the only piece of
104
+ /// information that we have at that point is the `DepNode` we are trying to
105
+ /// re-evaluate, we need some way to re-run a query from just that. This is what
106
+ /// `force_from_dep_node()` implements.
107
+ ///
108
+ /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
109
+ /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
110
+ /// is usually constructed by computing a stable hash of the query-key that the
111
+ /// `DepNode` corresponds to. Consequently, it is not in general possible to go
112
+ /// back from hash to query-key (since hash functions are not reversible). For
113
+ /// this reason `force_from_dep_node()` is expected to fail from time to time
114
+ /// because we just cannot find out, from the `DepNode` alone, what the
115
+ /// corresponding query-key is and therefore cannot re-run the query.
116
+ ///
117
+ /// The system deals with this case letting `try_mark_green` fail which forces
118
+ /// the root query to be re-evaluated.
119
+ ///
120
+ /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
121
+ /// Fortunately, we can use some contextual information that will allow us to
122
+ /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
123
+ /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
124
+ /// valid `DefPathHash`. Since we also always build a huge table that maps every
125
+ /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
126
+ /// everything we need to re-run the query.
127
+ ///
128
+ /// Take the `mir_promoted` query as an example. Like many other queries, it
129
+ /// just has a single parameter: the `DefId` of the item it will compute the
130
+ /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
131
+ /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
132
+ /// is actually a `DefPathHash`, and can therefore just look up the corresponding
133
+ /// `DefId` in `tcx.def_path_hash_to_def_id`.
134
+ ///
135
+ /// When you implement a new query, it will likely have a corresponding new
136
+ /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
137
+ /// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
138
+ /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
139
+ /// add it to the "We don't have enough information to reconstruct..." group in
140
+ /// the match below.
141
+ pub ( super ) force_from_dep_node : fn ( tcx : TyCtxt < ' _ > , dep_node : & DepNode ) -> bool ,
142
+
98
143
/// Invoke a query to put the on-disk cached value in memory.
99
144
pub ( super ) try_load_from_on_disk_cache : fn ( TyCtxt < ' _ > , & DepNode ) ,
100
145
}
@@ -156,7 +201,7 @@ macro_rules! contains_eval_always_attr {
156
201
pub mod dep_kind {
157
202
use super :: * ;
158
203
use crate :: ty:: query:: { queries, query_keys} ;
159
- use rustc_query_system:: query:: QueryDescription ;
204
+ use rustc_query_system:: query:: { force_query , QueryDescription } ;
160
205
161
206
// We use this for most things when incr. comp. is turned off.
162
207
pub const Null : DepKindStruct = DepKindStruct {
@@ -165,6 +210,7 @@ pub mod dep_kind {
165
210
is_eval_always : false ,
166
211
167
212
can_reconstruct_query_key : || true ,
213
+ force_from_dep_node : |_, dep_node| bug ! ( "force_from_dep_node: encountered {:?}" , dep_node) ,
168
214
try_load_from_on_disk_cache : |_, _| { } ,
169
215
} ;
170
216
@@ -175,6 +221,7 @@ pub mod dep_kind {
175
221
is_eval_always : true ,
176
222
177
223
can_reconstruct_query_key : || true ,
224
+ force_from_dep_node : |_, dep_node| bug ! ( "force_from_dep_node: encountered {:?}" , dep_node) ,
178
225
try_load_from_on_disk_cache : |_, _| { } ,
179
226
} ;
180
227
@@ -184,6 +231,7 @@ pub mod dep_kind {
184
231
is_eval_always : false ,
185
232
186
233
can_reconstruct_query_key : || false ,
234
+ force_from_dep_node : |_, _| false ,
187
235
try_load_from_on_disk_cache : |_, _| { } ,
188
236
} ;
189
237
@@ -193,6 +241,7 @@ pub mod dep_kind {
193
241
is_eval_always : false ,
194
242
195
243
can_reconstruct_query_key : || false ,
244
+ force_from_dep_node : |_, _| false ,
196
245
try_load_from_on_disk_cache : |_, _| { } ,
197
246
} ;
198
247
@@ -217,6 +266,24 @@ pub mod dep_kind {
217
266
<query_keys:: $variant<' _> as DepNodeParams <TyCtxt <' _>>>:: recover( tcx, dep_node)
218
267
}
219
268
269
+ fn force_from_dep_node( tcx: TyCtxt <' _>, dep_node: & DepNode ) -> bool {
270
+ if !can_reconstruct_query_key( ) {
271
+ return false ;
272
+ }
273
+
274
+ if let Some ( key) = recover( tcx, dep_node) {
275
+ force_query:: <queries:: $variant<' _>, _>(
276
+ tcx,
277
+ key,
278
+ DUMMY_SP ,
279
+ * dep_node
280
+ ) ;
281
+ return true ;
282
+ }
283
+
284
+ false
285
+ }
286
+
220
287
fn try_load_from_on_disk_cache( tcx: TyCtxt <' _>, dep_node: & DepNode ) {
221
288
if !can_reconstruct_query_key( ) {
222
289
return
@@ -238,6 +305,7 @@ pub mod dep_kind {
238
305
is_anon,
239
306
is_eval_always,
240
307
can_reconstruct_query_key,
308
+ force_from_dep_node,
241
309
try_load_from_on_disk_cache,
242
310
}
243
311
} ; ) *
0 commit comments