@@ -78,32 +78,70 @@ pub struct DepKindStruct {
7878 /// Anonymous queries cannot be replayed from one compiler invocation to the next.
7979 /// When their result is needed, it is recomputed. They are useful for fine-grained
8080 /// dependency tracking, and caching within one compiler invocation.
81- pub ( super ) is_anon : bool ,
81+ pub is_anon : bool ,
8282
8383 /// Eval-always queries do not track their dependencies, and are always recomputed, even if
8484 /// their inputs have not changed since the last compiler invocation. The result is still
8585 /// cached within one compiler invocation.
86- pub ( super ) is_eval_always : bool ,
86+ pub is_eval_always : bool ,
8787
8888 /// Whether the query key can be recovered from the hashed fingerprint.
8989 /// 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 ) ,
100138}
101139
102140impl DepKind {
103141 #[ inline( always) ]
104- pub fn fingerprint_style ( & self ) -> FingerprintStyle {
142+ pub fn fingerprint_style ( self , tcx : TyCtxt < ' _ > ) -> FingerprintStyle {
105143 // Only fetch the DepKindStruct once.
106- let data: & DepKindStruct = & * * self ;
144+ let data = tcx . query_kind ( self ) ;
107145 if data. is_anon {
108146 return FingerprintStyle :: Opaque ;
109147 }
@@ -112,94 +150,6 @@ impl DepKind {
112150 }
113151}
114152
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-
203153macro_rules! define_dep_nodes {
204154 ( <$tcx: tt>
205155 $(
@@ -212,9 +162,7 @@ macro_rules! define_dep_nodes {
212162 ( $mod: ident) => { [ $( ( $mod:: $variant) , ) * ] } ;
213163 }
214164
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`.
218166 #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , Encodable , Decodable ) ]
219167 #[ allow( non_camel_case_types) ]
220168 pub enum DepKind {
@@ -280,7 +228,7 @@ pub trait DepNodeExt: Sized {
280228 /// Construct a DepNode from the given DepKind and DefPathHash. This
281229 /// method will assert that the given DepKind actually requires a
282230 /// 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 ;
284232
285233 /// Extracts the DefId corresponding to this DepNode. This will work
286234 /// if two conditions are met:
@@ -295,7 +243,11 @@ pub trait DepNodeExt: Sized {
295243 fn extract_def_id ( & self , tcx : TyCtxt < ' _ > ) -> Option < DefId > ;
296244
297245 /// 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 , ( ) > ;
299251
300252 /// Used in testing
301253 fn has_label_string ( label : & str ) -> bool ;
@@ -305,8 +257,8 @@ impl DepNodeExt for DepNode {
305257 /// Construct a DepNode from the given DepKind and DefPathHash. This
306258 /// method will assert that the given DepKind actually requires a
307259 /// 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 ) ;
310262 DepNode { kind, hash : def_path_hash. 0 . into ( ) }
311263 }
312264
@@ -321,21 +273,27 @@ impl DepNodeExt for DepNode {
321273 /// refers to something from the previous compilation session that
322274 /// has been removed.
323275 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 {
325277 Some ( tcx. def_path_hash_to_def_id ( DefPathHash ( self . hash . into ( ) ) ) )
326278 } else {
327279 None
328280 }
329281 }
330282
331283 /// 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 , ( ) > {
333289 let kind = dep_kind_from_label_string ( label) ?;
334290
335- match kind. fingerprint_style ( ) {
291+ match kind. fingerprint_style ( tcx ) {
336292 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+ }
339297 }
340298 }
341299
0 commit comments