Skip to content

Commit cbce217

Browse files
committed
Remove the need for no_force
1 parent 6701215 commit cbce217

File tree

6 files changed

+148
-153
lines changed

6 files changed

+148
-153
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -362,29 +362,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
362362
[] CompileCodegenUnit(Symbol),
363363
]);
364364

365-
pub trait RecoverKey<'tcx>: Sized {
366-
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
367-
}
368-
369-
impl RecoverKey<'tcx> for CrateNum {
370-
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
371-
dep_node.extract_def_id(tcx).map(|id| id.krate)
372-
}
373-
}
374-
375-
impl RecoverKey<'tcx> for DefId {
376-
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
377-
dep_node.extract_def_id(tcx)
378-
}
379-
}
380-
381-
impl RecoverKey<'tcx> for DefIndex {
382-
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
383-
dep_node.extract_def_id(tcx).map(|id| id.index)
384-
}
385-
}
386-
387-
trait DepNodeParams<'tcx>: fmt::Debug {
365+
pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
388366
const CAN_RECONSTRUCT_QUERY_KEY: bool;
389367

390368
/// This method turns the parameters of a DepNodeConstructor into an opaque
@@ -398,6 +376,8 @@ trait DepNodeParams<'tcx>: fmt::Debug {
398376
fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
399377
format!("{:?}", self)
400378
}
379+
380+
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
401381
}
402382

403383
impl<'tcx, T> DepNodeParams<'tcx> for T
@@ -418,6 +398,10 @@ where
418398
default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
419399
format!("{:?}", *self)
420400
}
401+
402+
default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
403+
None
404+
}
421405
}
422406

423407
impl<'tcx> DepNodeParams<'tcx> for DefId {
@@ -430,6 +414,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefId {
430414
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
431415
tcx.def_path_str(*self)
432416
}
417+
418+
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
419+
dep_node.extract_def_id(tcx)
420+
}
433421
}
434422

435423
impl<'tcx> DepNodeParams<'tcx> for DefIndex {
@@ -442,6 +430,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefIndex {
442430
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
443431
tcx.def_path_str(DefId::local(*self))
444432
}
433+
434+
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
435+
dep_node.extract_def_id(tcx).map(|id| id.index)
436+
}
445437
}
446438

447439
impl<'tcx> DepNodeParams<'tcx> for CrateNum {
@@ -455,6 +447,10 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum {
455447
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
456448
tcx.crate_name(*self).to_string()
457449
}
450+
451+
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
452+
dep_node.extract_def_id(tcx).map(|id| id.krate)
453+
}
458454
}
459455

460456
impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) {

src/librustc/dep_graph/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ mod query;
66
mod safe;
77
mod serialized;
88

9-
pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, RecoverKey, WorkProductId};
9+
pub(crate) use self::dep_node::DepNodeParams;
10+
pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId};
1011
pub use self::graph::WorkProductFileKind;
1112
pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
1213
pub use self::prev::PreviousDepGraph;

src/librustc/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
1+
use crate::dep_graph::SerializedDepNodeIndex;
22
use crate::mir;
33
use crate::mir::interpret::{GlobalId, LitToConstInput};
44
use crate::traits;

src/librustc/ty/query/mod.rs

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::dep_graph::{self, DepConstructor, DepNode};
1+
use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
22
use crate::hir::exports::Export;
33
use crate::infer::canonical::{self, Canonical};
44
use crate::lint::LintLevelMap;
@@ -60,8 +60,8 @@ use std::sync::Arc;
6060

6161
#[macro_use]
6262
mod plumbing;
63+
pub use self::plumbing::CycleError;
6364
use self::plumbing::*;
64-
pub use self::plumbing::{force_from_dep_node, CycleError};
6565

6666
mod stats;
6767
pub use self::stats::print_stats;
@@ -105,3 +105,104 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder
105105
// as they will raise an fatal error on query cycles instead.
106106

107107
rustc_query_append! { [define_queries!][<'tcx>] }
108+
109+
/// The red/green evaluation system will try to mark a specific DepNode in the
110+
/// dependency graph as green by recursively trying to mark the dependencies of
111+
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
112+
/// where we don't know if it is red or green and we therefore actually have
113+
/// to recompute its value in order to find out. Since the only piece of
114+
/// information that we have at that point is the `DepNode` we are trying to
115+
/// re-evaluate, we need some way to re-run a query from just that. This is what
116+
/// `force_from_dep_node()` implements.
117+
///
118+
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
119+
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
120+
/// is usually constructed by computing a stable hash of the query-key that the
121+
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
122+
/// back from hash to query-key (since hash functions are not reversible). For
123+
/// this reason `force_from_dep_node()` is expected to fail from time to time
124+
/// because we just cannot find out, from the `DepNode` alone, what the
125+
/// corresponding query-key is and therefore cannot re-run the query.
126+
///
127+
/// The system deals with this case letting `try_mark_green` fail which forces
128+
/// the root query to be re-evaluated.
129+
///
130+
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
131+
/// Fortunately, we can use some contextual information that will allow us to
132+
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
133+
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
134+
/// valid `DefPathHash`. Since we also always build a huge table that maps every
135+
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
136+
/// everything we need to re-run the query.
137+
///
138+
/// Take the `mir_validated` query as an example. Like many other queries, it
139+
/// just has a single parameter: the `DefId` of the item it will compute the
140+
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
141+
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
142+
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
143+
/// `DefId` in `tcx.def_path_hash_to_def_id`.
144+
///
145+
/// When you implement a new query, it will likely have a corresponding new
146+
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
147+
/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
148+
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
149+
/// add it to the "We don't have enough information to reconstruct..." group in
150+
/// the match below.
151+
pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
152+
use crate::dep_graph::DepKind;
153+
154+
// We must avoid ever having to call `force_from_dep_node()` for a
155+
// `DepNode::codegen_unit`:
156+
// Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
157+
// would always end up having to evaluate the first caller of the
158+
// `codegen_unit` query that *is* reconstructible. This might very well be
159+
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
160+
// to re-trigger calling the `codegen_unit` query with the right key. At
161+
// that point we would already have re-done all the work we are trying to
162+
// avoid doing in the first place.
163+
// The solution is simple: Just explicitly call the `codegen_unit` query for
164+
// each CGU, right after partitioning. This way `try_mark_green` will always
165+
// hit the cache instead of having to go through `force_from_dep_node`.
166+
// This assertion makes sure, we actually keep applying the solution above.
167+
debug_assert!(
168+
dep_node.kind != DepKind::codegen_unit,
169+
"calling force_from_dep_node() on DepKind::codegen_unit"
170+
);
171+
172+
if !dep_node.kind.can_reconstruct_query_key() {
173+
return false;
174+
}
175+
176+
rustc_dep_node_force!([dep_node, tcx]
177+
// These are inputs that are expected to be pre-allocated and that
178+
// should therefore always be red or green already.
179+
DepKind::AllLocalTraitImpls |
180+
DepKind::CrateMetadata |
181+
DepKind::HirBody |
182+
DepKind::Hir |
183+
184+
// These are anonymous nodes.
185+
DepKind::TraitSelect |
186+
187+
// We don't have enough information to reconstruct the query key of
188+
// these.
189+
DepKind::CompileCodegenUnit => {
190+
bug!("force_from_dep_node: encountered {:?}", dep_node)
191+
}
192+
);
193+
194+
false
195+
}
196+
197+
impl DepNode {
198+
/// Check whether the query invocation corresponding to the given
199+
/// DepNode is eligible for on-disk-caching. If so, this is method
200+
/// will execute the query corresponding to the given DepNode.
201+
/// Also, as a sanity check, it expects that the corresponding query
202+
/// invocation has been marked as green already.
203+
pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) {
204+
use crate::dep_graph::DepKind;
205+
206+
rustc_dep_node_try_load_from_on_disk_cache!(self, tcx)
207+
}
208+
}

src/librustc/ty/query/plumbing.rs

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! generate the actual methods on tcx which find and execute the provider,
33
//! manage the caches, and so forth.
44
5-
use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
5+
use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
66
use crate::ty::query::caches::QueryCache;
77
use crate::ty::query::config::{QueryAccessors, QueryDescription};
88
use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId};
@@ -720,7 +720,7 @@ impl<'tcx> TyCtxt<'tcx> {
720720
}
721721

722722
#[allow(dead_code)]
723-
fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
723+
pub(super) fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
724724
self,
725725
key: Q::Key,
726726
span: Span,
@@ -1162,91 +1162,3 @@ macro_rules! define_provider_struct {
11621162
}
11631163
};
11641164
}
1165-
1166-
/// The red/green evaluation system will try to mark a specific DepNode in the
1167-
/// dependency graph as green by recursively trying to mark the dependencies of
1168-
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
1169-
/// where we don't know if it is red or green and we therefore actually have
1170-
/// to recompute its value in order to find out. Since the only piece of
1171-
/// information that we have at that point is the `DepNode` we are trying to
1172-
/// re-evaluate, we need some way to re-run a query from just that. This is what
1173-
/// `force_from_dep_node()` implements.
1174-
///
1175-
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
1176-
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
1177-
/// is usually constructed by computing a stable hash of the query-key that the
1178-
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
1179-
/// back from hash to query-key (since hash functions are not reversible). For
1180-
/// this reason `force_from_dep_node()` is expected to fail from time to time
1181-
/// because we just cannot find out, from the `DepNode` alone, what the
1182-
/// corresponding query-key is and therefore cannot re-run the query.
1183-
///
1184-
/// The system deals with this case letting `try_mark_green` fail which forces
1185-
/// the root query to be re-evaluated.
1186-
///
1187-
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
1188-
/// Fortunately, we can use some contextual information that will allow us to
1189-
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
1190-
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
1191-
/// valid `DefPathHash`. Since we also always build a huge table that maps every
1192-
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
1193-
/// everything we need to re-run the query.
1194-
///
1195-
/// Take the `mir_validated` query as an example. Like many other queries, it
1196-
/// just has a single parameter: the `DefId` of the item it will compute the
1197-
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
1198-
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
1199-
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
1200-
/// `DefId` in `tcx.def_path_hash_to_def_id`.
1201-
///
1202-
/// When you implement a new query, it will likely have a corresponding new
1203-
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
1204-
/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
1205-
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
1206-
/// add it to the "We don't have enough information to reconstruct..." group in
1207-
/// the match below.
1208-
pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
1209-
use crate::dep_graph::RecoverKey;
1210-
1211-
// We must avoid ever having to call `force_from_dep_node()` for a
1212-
// `DepNode::codegen_unit`:
1213-
// Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
1214-
// would always end up having to evaluate the first caller of the
1215-
// `codegen_unit` query that *is* reconstructible. This might very well be
1216-
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
1217-
// to re-trigger calling the `codegen_unit` query with the right key. At
1218-
// that point we would already have re-done all the work we are trying to
1219-
// avoid doing in the first place.
1220-
// The solution is simple: Just explicitly call the `codegen_unit` query for
1221-
// each CGU, right after partitioning. This way `try_mark_green` will always
1222-
// hit the cache instead of having to go through `force_from_dep_node`.
1223-
// This assertion makes sure, we actually keep applying the solution above.
1224-
debug_assert!(
1225-
dep_node.kind != DepKind::codegen_unit,
1226-
"calling force_from_dep_node() on DepKind::codegen_unit"
1227-
);
1228-
1229-
if !dep_node.kind.can_reconstruct_query_key() {
1230-
return false;
1231-
}
1232-
1233-
rustc_dep_node_force!([dep_node, tcx]
1234-
// These are inputs that are expected to be pre-allocated and that
1235-
// should therefore always be red or green already.
1236-
DepKind::AllLocalTraitImpls |
1237-
DepKind::CrateMetadata |
1238-
DepKind::HirBody |
1239-
DepKind::Hir |
1240-
1241-
// These are anonymous nodes.
1242-
DepKind::TraitSelect |
1243-
1244-
// We don't have enough information to reconstruct the query key of
1245-
// these.
1246-
DepKind::CompileCodegenUnit => {
1247-
bug!("force_from_dep_node: encountered {:?}", dep_node)
1248-
}
1249-
);
1250-
1251-
true
1252-
}

0 commit comments

Comments
 (0)