@@ -78,32 +78,70 @@ pub struct DepKindStruct {
78
78
/// Anonymous queries cannot be replayed from one compiler invocation to the next.
79
79
/// When their result is needed, it is recomputed. They are useful for fine-grained
80
80
/// dependency tracking, and caching within one compiler invocation.
81
- pub ( super ) is_anon : bool ,
81
+ pub is_anon : bool ,
82
82
83
83
/// Eval-always queries do not track their dependencies, and are always recomputed, even if
84
84
/// their inputs have not changed since the last compiler invocation. The result is still
85
85
/// cached within one compiler invocation.
86
- pub ( super ) is_eval_always : bool ,
86
+ pub is_eval_always : bool ,
87
87
88
88
/// Whether the query key can be recovered from the hashed fingerprint.
89
89
/// See [DepNodeParams] trait for the behaviour of each key type.
90
- // FIXME: Make this a simple boolean once DepNodeParams::fingerprint_style
91
- // can be made a specialized associated const.
92
- fingerprint_style : fn ( ) -> FingerprintStyle ,
93
- }
94
-
95
- impl std:: ops:: Deref for DepKind {
96
- type Target = DepKindStruct ;
97
- fn deref ( & self ) -> & DepKindStruct {
98
- & DEP_KINDS [ * self as usize ]
99
- }
90
+ pub fingerprint_style : fn ( ) -> FingerprintStyle ,
91
+
92
+ /// The red/green evaluation system will try to mark a specific DepNode in the
93
+ /// dependency graph as green by recursively trying to mark the dependencies of
94
+ /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
95
+ /// where we don't know if it is red or green and we therefore actually have
96
+ /// to recompute its value in order to find out. Since the only piece of
97
+ /// information that we have at that point is the `DepNode` we are trying to
98
+ /// re-evaluate, we need some way to re-run a query from just that. This is what
99
+ /// `force_from_dep_node()` implements.
100
+ ///
101
+ /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
102
+ /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
103
+ /// is usually constructed by computing a stable hash of the query-key that the
104
+ /// `DepNode` corresponds to. Consequently, it is not in general possible to go
105
+ /// back from hash to query-key (since hash functions are not reversible). For
106
+ /// this reason `force_from_dep_node()` is expected to fail from time to time
107
+ /// because we just cannot find out, from the `DepNode` alone, what the
108
+ /// corresponding query-key is and therefore cannot re-run the query.
109
+ ///
110
+ /// The system deals with this case letting `try_mark_green` fail which forces
111
+ /// the root query to be re-evaluated.
112
+ ///
113
+ /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
114
+ /// Fortunately, we can use some contextual information that will allow us to
115
+ /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
116
+ /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
117
+ /// valid `DefPathHash`. Since we also always build a huge table that maps every
118
+ /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
119
+ /// everything we need to re-run the query.
120
+ ///
121
+ /// Take the `mir_promoted` query as an example. Like many other queries, it
122
+ /// just has a single parameter: the `DefId` of the item it will compute the
123
+ /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
124
+ /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
125
+ /// is actually a `DefPathHash`, and can therefore just look up the corresponding
126
+ /// `DefId` in `tcx.def_path_hash_to_def_id`.
127
+ ///
128
+ /// When you implement a new query, it will likely have a corresponding new
129
+ /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
130
+ /// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
131
+ /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
132
+ /// add it to the "We don't have enough information to reconstruct..." group in
133
+ /// the match below.
134
+ pub force_from_dep_node : fn ( tcx : TyCtxt < ' _ > , dep_node : & DepNode ) -> bool ,
135
+
136
+ /// Invoke a query to put the on-disk cached value in memory.
137
+ pub try_load_from_on_disk_cache : fn ( TyCtxt < ' _ > , & DepNode ) ,
100
138
}
101
139
102
140
impl DepKind {
103
141
#[ inline( always) ]
104
- pub fn fingerprint_style ( & self ) -> FingerprintStyle {
142
+ pub fn fingerprint_style ( self , tcx : TyCtxt < ' _ > ) -> FingerprintStyle {
105
143
// Only fetch the DepKindStruct once.
106
- let data: & DepKindStruct = & * * self ;
144
+ let data = tcx . query_kind ( self ) ;
107
145
if data. is_anon {
108
146
return FingerprintStyle :: Opaque ;
109
147
}
@@ -112,94 +150,6 @@ impl DepKind {
112
150
}
113
151
}
114
152
115
- macro_rules! is_anon_attr {
116
- ( anon) => {
117
- true
118
- } ;
119
- ( $attr: ident) => {
120
- false
121
- } ;
122
- }
123
-
124
- macro_rules! is_eval_always_attr {
125
- ( eval_always) => {
126
- true
127
- } ;
128
- ( $attr: ident) => {
129
- false
130
- } ;
131
- }
132
-
133
- macro_rules! contains_anon_attr {
134
- ( $( ( $attr: ident $( $attr_args: tt) * ) ) ,* ) => ( { $( is_anon_attr!( $attr) | ) * false } ) ;
135
- }
136
-
137
- macro_rules! contains_eval_always_attr {
138
- ( $( ( $attr: ident $( $attr_args: tt) * ) ) ,* ) => ( { $( is_eval_always_attr!( $attr) | ) * false } ) ;
139
- }
140
-
141
- #[ allow( non_upper_case_globals) ]
142
- pub mod dep_kind {
143
- use super :: * ;
144
- use crate :: ty:: query:: query_keys;
145
- use rustc_query_system:: dep_graph:: FingerprintStyle ;
146
-
147
- // We use this for most things when incr. comp. is turned off.
148
- pub const Null : DepKindStruct = DepKindStruct {
149
- is_anon : false ,
150
- is_eval_always : false ,
151
-
152
- fingerprint_style : || FingerprintStyle :: Unit ,
153
- } ;
154
-
155
- pub const TraitSelect : DepKindStruct = DepKindStruct {
156
- is_anon : true ,
157
- is_eval_always : false ,
158
-
159
- fingerprint_style : || FingerprintStyle :: Unit ,
160
- } ;
161
-
162
- pub const CompileCodegenUnit : DepKindStruct = DepKindStruct {
163
- is_anon : false ,
164
- is_eval_always : false ,
165
-
166
- fingerprint_style : || FingerprintStyle :: Opaque ,
167
- } ;
168
-
169
- pub const CompileMonoItem : DepKindStruct = DepKindStruct {
170
- is_anon : false ,
171
- is_eval_always : false ,
172
-
173
- fingerprint_style : || FingerprintStyle :: Opaque ,
174
- } ;
175
-
176
- macro_rules! define_query_dep_kinds {
177
- ( $(
178
- [ $( $attrs: tt) * ]
179
- $variant: ident $( ( $tuple_arg_ty: ty $( , ) ? ) ) *
180
- , ) * ) => (
181
- $( pub const $variant: DepKindStruct = {
182
- const is_anon: bool = contains_anon_attr!( $( $attrs) * ) ;
183
- const is_eval_always: bool = contains_eval_always_attr!( $( $attrs) * ) ;
184
-
185
- #[ inline( always) ]
186
- fn fingerprint_style( ) -> rustc_query_system:: dep_graph:: FingerprintStyle {
187
- <query_keys:: $variant<' _> as DepNodeParams <TyCtxt <' _>>>
188
- :: fingerprint_style( )
189
- }
190
-
191
- DepKindStruct {
192
- is_anon,
193
- is_eval_always,
194
- fingerprint_style,
195
- }
196
- } ; ) *
197
- ) ;
198
- }
199
-
200
- rustc_dep_node_append ! ( [ define_query_dep_kinds!] [ ] ) ;
201
- }
202
-
203
153
macro_rules! define_dep_nodes {
204
154
( <$tcx: tt>
205
155
$(
@@ -212,9 +162,7 @@ macro_rules! define_dep_nodes {
212
162
( $mod: ident) => { [ $( ( $mod:: $variant) , ) * ] } ;
213
163
}
214
164
215
- static DEP_KINDS : & [ DepKindStruct ] = & make_dep_kind_array!( dep_kind) ;
216
-
217
- /// This enum serves as an index into the `DEP_KINDS` array.
165
+ /// This enum serves as an index into arrays built by `make_dep_kind_array`.
218
166
#[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , Encodable , Decodable ) ]
219
167
#[ allow( non_camel_case_types) ]
220
168
pub enum DepKind {
@@ -280,7 +228,7 @@ pub trait DepNodeExt: Sized {
280
228
/// Construct a DepNode from the given DepKind and DefPathHash. This
281
229
/// method will assert that the given DepKind actually requires a
282
230
/// single DefId/DefPathHash parameter.
283
- fn from_def_path_hash ( def_path_hash : DefPathHash , kind : DepKind ) -> Self ;
231
+ fn from_def_path_hash ( tcx : TyCtxt < ' _ > , def_path_hash : DefPathHash , kind : DepKind ) -> Self ;
284
232
285
233
/// Extracts the DefId corresponding to this DepNode. This will work
286
234
/// if two conditions are met:
@@ -295,7 +243,11 @@ pub trait DepNodeExt: Sized {
295
243
fn extract_def_id ( & self , tcx : TyCtxt < ' _ > ) -> Option < DefId > ;
296
244
297
245
/// Used in testing
298
- fn from_label_string ( label : & str , def_path_hash : DefPathHash ) -> Result < Self , ( ) > ;
246
+ fn from_label_string (
247
+ tcx : TyCtxt < ' _ > ,
248
+ label : & str ,
249
+ def_path_hash : DefPathHash ,
250
+ ) -> Result < Self , ( ) > ;
299
251
300
252
/// Used in testing
301
253
fn has_label_string ( label : & str ) -> bool ;
@@ -305,8 +257,8 @@ impl DepNodeExt for DepNode {
305
257
/// Construct a DepNode from the given DepKind and DefPathHash. This
306
258
/// method will assert that the given DepKind actually requires a
307
259
/// single DefId/DefPathHash parameter.
308
- fn from_def_path_hash ( def_path_hash : DefPathHash , kind : DepKind ) -> DepNode {
309
- debug_assert ! ( kind. fingerprint_style( ) == FingerprintStyle :: DefPathHash ) ;
260
+ fn from_def_path_hash ( tcx : TyCtxt < ' _ > , def_path_hash : DefPathHash , kind : DepKind ) -> DepNode {
261
+ debug_assert ! ( kind. fingerprint_style( tcx ) == FingerprintStyle :: DefPathHash ) ;
310
262
DepNode { kind, hash : def_path_hash. 0 . into ( ) }
311
263
}
312
264
@@ -321,21 +273,27 @@ impl DepNodeExt for DepNode {
321
273
/// refers to something from the previous compilation session that
322
274
/// has been removed.
323
275
fn extract_def_id ( & self , tcx : TyCtxt < ' tcx > ) -> Option < DefId > {
324
- if self . kind . fingerprint_style ( ) == FingerprintStyle :: DefPathHash {
276
+ if self . kind . fingerprint_style ( tcx ) == FingerprintStyle :: DefPathHash {
325
277
Some ( tcx. def_path_hash_to_def_id ( DefPathHash ( self . hash . into ( ) ) ) )
326
278
} else {
327
279
None
328
280
}
329
281
}
330
282
331
283
/// Used in testing
332
- fn from_label_string ( label : & str , def_path_hash : DefPathHash ) -> Result < DepNode , ( ) > {
284
+ fn from_label_string (
285
+ tcx : TyCtxt < ' _ > ,
286
+ label : & str ,
287
+ def_path_hash : DefPathHash ,
288
+ ) -> Result < DepNode , ( ) > {
333
289
let kind = dep_kind_from_label_string ( label) ?;
334
290
335
- match kind. fingerprint_style ( ) {
291
+ match kind. fingerprint_style ( tcx ) {
336
292
FingerprintStyle :: Opaque => Err ( ( ) ) ,
337
- FingerprintStyle :: Unit => Ok ( DepNode :: new_no_params ( kind) ) ,
338
- FingerprintStyle :: DefPathHash => Ok ( DepNode :: from_def_path_hash ( def_path_hash, kind) ) ,
293
+ FingerprintStyle :: Unit => Ok ( DepNode :: new_no_params ( tcx, kind) ) ,
294
+ FingerprintStyle :: DefPathHash => {
295
+ Ok ( DepNode :: from_def_path_hash ( tcx, def_path_hash, kind) )
296
+ }
339
297
}
340
298
}
341
299
0 commit comments