Skip to content

Commit b09de95

Browse files
committed
Merge two query callbacks arrays.
1 parent dc71433 commit b09de95

File tree

12 files changed

+180
-247
lines changed

12 files changed

+180
-247
lines changed

compiler/rustc_incremental/src/assert_dep_graph.rs

+23-17
Original file line numberDiff line numberDiff line change
@@ -126,30 +126,36 @@ impl IfThisChanged<'tcx> {
126126
if attr.has_name(sym::rustc_if_this_changed) {
127127
let dep_node_interned = self.argument(attr);
128128
let dep_node = match dep_node_interned {
129-
None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner),
130-
Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) {
131-
Ok(n) => n,
132-
Err(()) => {
133-
self.tcx.sess.span_fatal(
134-
attr.span,
135-
&format!("unrecognized DepNode variant {:?}", n),
136-
);
129+
None => {
130+
DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner)
131+
}
132+
Some(n) => {
133+
match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) {
134+
Ok(n) => n,
135+
Err(()) => {
136+
self.tcx.sess.span_fatal(
137+
attr.span,
138+
&format!("unrecognized DepNode variant {:?}", n),
139+
);
140+
}
137141
}
138-
},
142+
}
139143
};
140144
self.if_this_changed.push((attr.span, def_id.to_def_id(), dep_node));
141145
} else if attr.has_name(sym::rustc_then_this_would_need) {
142146
let dep_node_interned = self.argument(attr);
143147
let dep_node = match dep_node_interned {
144-
Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) {
145-
Ok(n) => n,
146-
Err(()) => {
147-
self.tcx.sess.span_fatal(
148-
attr.span,
149-
&format!("unrecognized DepNode variant {:?}", n),
150-
);
148+
Some(n) => {
149+
match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) {
150+
Ok(n) => n,
151+
Err(()) => {
152+
self.tcx.sess.span_fatal(
153+
attr.span,
154+
&format!("unrecognized DepNode variant {:?}", n),
155+
);
156+
}
151157
}
152-
},
158+
}
153159
None => {
154160
self.tcx.sess.span_fatal(attr.span, "missing DepNode variant");
155161
}

compiler/rustc_incremental/src/persist/dirty_clean.rs

+6-15
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use rustc_ast::{self as ast, Attribute, NestedMetaItem};
1616
use rustc_data_structures::fx::FxHashSet;
1717
use rustc_hir as hir;
18-
use rustc_hir::def_id::{DefId, LocalDefId};
18+
use rustc_hir::def_id::LocalDefId;
1919
use rustc_hir::intravisit;
2020
use rustc_hir::itemlikevisit::ItemLikeVisitor;
2121
use rustc_hir::Node as HirNode;
@@ -302,18 +302,6 @@ impl DirtyCleanVisitor<'tcx> {
302302
out
303303
}
304304

305-
fn dep_nodes<'l>(
306-
&self,
307-
labels: &'l Labels,
308-
def_id: DefId,
309-
) -> impl Iterator<Item = DepNode> + 'l {
310-
let def_path_hash = self.tcx.def_path_hash(def_id);
311-
labels.iter().map(move |label| match DepNode::from_label_string(label, def_path_hash) {
312-
Ok(dep_node) => dep_node,
313-
Err(()) => unreachable!("label: {}", label),
314-
})
315-
}
316-
317305
fn dep_node_str(&self, dep_node: &DepNode) -> String {
318306
if let Some(def_id) = dep_node.extract_def_id(self.tcx) {
319307
format!("{:?}({})", dep_node.kind, self.tcx.def_path_str(def_id))
@@ -345,16 +333,19 @@ impl DirtyCleanVisitor<'tcx> {
345333
}
346334

347335
fn check_item(&mut self, item_id: LocalDefId, item_span: Span) {
336+
let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id());
348337
for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
349338
let assertion = match self.assertion_maybe(item_id, attr) {
350339
Some(a) => a,
351340
None => continue,
352341
};
353342
self.checked_attrs.insert(attr.id);
354-
for dep_node in self.dep_nodes(&assertion.clean, item_id.to_def_id()) {
343+
for label in assertion.clean {
344+
let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap();
355345
self.assert_clean(item_span, dep_node);
356346
}
357-
for dep_node in self.dep_nodes(&assertion.dirty, item_id.to_def_id()) {
347+
for label in assertion.dirty {
348+
let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap();
358349
self.assert_dirty(item_span, dep_node);
359350
}
360351
}

compiler/rustc_interface/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ pub fn create_global_ctxt<'tcx>(
838838
dep_graph,
839839
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
840840
queries.as_dyn(),
841+
&rustc_query_impl::QUERY_CALLBACKS,
841842
crate_name,
842843
outputs,
843844
)

compiler/rustc_middle/src/dep_graph/dep_node.rs

+72-114
Original file line numberDiff line numberDiff line change
@@ -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

102140
impl 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-
203153
macro_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

Comments
 (0)