about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSteve Klabnik <steve@steveklabnik.com>2017-10-10 20:22:26 -0400
committerGitHub <noreply@github.com>2017-10-10 20:22:26 -0400
commit0a0bec7695a2a7bf46fd3d58eed90ce847147ac0 (patch)
treebb2f1b4b627d866fdfaaf6e2af84de3bf6b5edc3
parentfab96c4b1201977f8875388611be5481079f5cf2 (diff)
parenteb1006f5cfb9429d76423bea5360d59a818fbc43 (diff)
downloadrust-0a0bec7695a2a7bf46fd3d58eed90ce847147ac0.tar.gz
rust-0a0bec7695a2a7bf46fd3d58eed90ce847147ac0.zip
Rollup merge of #45139 - michaelwoerister:document-force_from_dep_node, r=nikomatsakis
incr.comp.: Add some documentation to force_from_dep_node().

r? @nikomatsakis
-rw-r--r--src/librustc/ty/maps/plumbing.rs51
1 files changed, 47 insertions, 4 deletions
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 88b619558d9..389b0401b86 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 |