From eb1006f5cfb9429d76423bea5360d59a818fbc43 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 9 Oct 2017 17:29:59 +0200 Subject: [PATCH] incr.comp.: Add some documentation to force_from_dep_node(). --- src/librustc/ty/maps/plumbing.rs | 51 +++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 88b619558d90b..389b0401b86ab 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -603,6 +603,49 @@ macro_rules! define_provider_struct { }; } + +/// The red/green evaluation system will try to mark a specific DepNode in the +/// dependency graph as green by recursively trying to mark the dependencies of +/// that DepNode as green. While doing so, it will sometimes encounter a DepNode +/// where we don't know if it is red or green and we therefore actually have +/// to recompute its value in order to find out. Since the only piece of +/// information that we have at that point is the DepNode we are trying to +/// re-evaluate, we need some way to re-run a query from just that. This is what +/// `force_from_dep_node()` implements. +/// +/// In the general case, a DepNode consists of a DepKind and an opaque +/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint +/// is usually constructed by computing a stable hash of the query-key that the +/// DepNode corresponds to. Consequently, it is not in general possible to go +/// back from hash to query-key (since hash functions are not reversible). For +/// this reason `force_from_dep_node()` is expected to fail from time to time +/// because we just cannot find out, from the DepNode alone, what the +/// corresponding query-key is and therefore cannot re-run the query. +/// +/// The system deals with this case letting `try_mark_green` fail which forces +/// the root query to be re-evaluated. +/// +/// Now, if force_from_dep_node() would always fail, it would be pretty useless. +/// Fortunately, we can use some contextual information that will allow us to +/// reconstruct query-keys for certain kinds of DepNodes. In particular, we +/// enforce by construction that the GUID/fingerprint of certain DepNodes is a +/// valid DefPathHash. Since we also always build a huge table that maps every +/// DefPathHash in the current codebase to the corresponding DefId, we have +/// everything we need to re-run the query. +/// +/// Take the `mir_validated` query as an example. Like many other queries, it +/// just has a single parameter: the DefId of the item it will compute the +/// validated MIR for. Now, when we call `force_from_dep_node()` on a dep-node +/// with kind `MirValidated`, we know that the GUID/fingerprint of the dep-node +/// is actually a DefPathHash, and can therefore just look up the corresponding +/// DefId in `tcx.def_path_hash_to_def_id`. +/// +/// When you implement a new query, it will likely have a corresponding new +/// DepKind, and you'll have to support it here in `force_from_dep_node()`. As +/// a rule of thumb, if your query takes a DefId or DefIndex as sole parameter, +/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just +/// add it to the "We don't have enough information to reconstruct..." group in +/// the match below. pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, dep_node: &DepNode) -> bool { @@ -687,16 +730,16 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::Hir | // This are anonymous nodes + DepKind::TraitSelect | + + // We don't have enough information to reconstruct the query key of + // these DepKind::IsCopy | DepKind::IsSized | DepKind::IsFreeze | DepKind::NeedsDrop | DepKind::Layout | - DepKind::TraitSelect | DepKind::ConstEval | - - // We don't have enough information to reconstruct the query key of - // these DepKind::InstanceSymbolName | DepKind::MirShim | DepKind::BorrowCheckKrate |