]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/variance/README.md
factor variances into a proper query
[rust.git] / src / librustc_typeck / variance / README.md
index ac785e4058bdee48833ab9e27a6ff8c37035047b..9ec20c1a45c347c9dfd2bae71c320092db1227ec 100644 (file)
@@ -97,51 +97,29 @@ types involved before considering variance.
 
 #### Dependency graph management
 
-Because variance works in two phases, if we are not careful, we wind
-up with a muddled mess of a dep-graph. Basically, when gathering up
-the constraints, things are fairly well-structured, but then we do a
-fixed-point iteration and write the results back where they
-belong. You can't give this fixed-point iteration a single task
-because it reads from (and writes to) the variance of all types in the
-crate. In principle, we *could* switch the "current task" in a very
-fine-grained way while propagating constraints in the fixed-point
-iteration and everything would be automatically tracked, but that
-would add some overhead and isn't really necessary anyway.
-
-Instead what we do is to add edges into the dependency graph as we
-construct the constraint set: so, if computing the constraints for
-node `X` requires loading the inference variables from node `Y`, then
-we can add an edge `Y -> X`, since the variance we ultimately infer
-for `Y` will affect the variance we ultimately infer for `X`.
-
-At this point, we've basically mirrored the inference graph in the
-dependency graph. This means we can just completely ignore the
-fixed-point iteration, since it is just shuffling values along this
-graph. In other words, if we added the fine-grained switching of tasks
-I described earlier, all it would show is that we repeatedly read the
-values described by the constraints, but those edges were already
-added when building the constraints in the first place.
-
-Here is how this is implemented (at least as of the time of this
-writing). The associated `DepNode` for the variance map is (at least
-presently) `Signature(DefId)`. This means that, in `constraints.rs`,
-when we visit an item to load up its constraints, we set
-`Signature(DefId)` as the current task (the "memoization" pattern
-described in the `dep-graph` README). Then whenever we find an
-embedded type or trait, we add a synthetic read of `Signature(DefId)`,
-which covers the variances we will compute for all of its
-parameters. This read is synthetic (i.e., we call
-`variance_map.read()`) because, in fact, the final variance is not yet
-computed -- the read *will* occur (repeatedly) during the fixed-point
-iteration phase.
-
-In fact, we don't really *need* this synthetic read. That's because we
-do wind up looking up the `TypeScheme` or `TraitDef` for all
-references types/traits, and those reads add an edge from
-`Signature(DefId)` (that is, they share the same dep node as
-variance). However, I've kept the synthetic reads in place anyway,
-just for future-proofing (in case we change the dep-nodes in the
-future), and because it makes the intention a bit clearer I think.
+Because variance is a whole-crate inference, its dependency graph
+can become quite muddled if we are not careful. To resolve this, we refactor
+into two queries:
+
+- `crate_variances` computes the variance for all items in the current crate.
+- `item_variances` accesses the variance for an individual reading; it
+  works by requesting `crate_variances` and extracting the relevant data.
+  
+If you limit yourself to reading `item_variances`, your code will only
+depend then on the inference inferred for that particular item.
+
+Eventually, the goal is to rely on the red-green dependency management
+algorithm. At the moment, however, we rely instead on a hack, where
+`item_variances` ignores the dependencies of accessing
+`crate_variances` and instead computes the *correct* dependencies
+itself. To this end, when we build up the constraints in the system,
+we also built up a transitive `dependencies` relation as part of the
+crate map. A `(X, Y)` pair is added to the map each time we have a
+constraint that the variance of some inferred for the item `X` depends
+on the variance of some element of `Y`. This is to some extent a
+mirroring of the inference graph in the dependency graph. This means
+we can just completely ignore the fixed-point iteration, since it is
+just shuffling values along this graph.
 
 ### Addendum: Variance on traits