Note [growThetaTyVars vs closeWrtFunDeps]

GHC/Tc/Solver.hs:2081 compiler

GHC has two functions, growThetaTyVars and closeWrtFunDeps, both with
the same type and similar behavior. This Note outlines the differences
and why we use one or the other.

Both functions take a list of constraints. We will call these the
*candidates*.

closeWrtFunDeps takes a set of "determined" type variables and finds the
closure of that set with respect to the functional dependencies
within the class constraints in the set of candidates. So, if we
have

  class C a b | a -> b
  class D a b   -- no fundep
  candidates = {C (Maybe a) (Either b c), D (Maybe a) (Either d e)}

then closeWrtFunDeps {a} will return the set {a,b,c}.
This is because, if `a` is determined, then `b` and `c` are, too,
by functional dependency. closeWrtFunDeps called with any seed set not including
`a` will just return its argument, as only `a` determines any other
type variable (in this example).

growThetaTyVars operates similarly, but it behaves as if every
constraint has a functional dependency among all its arguments.
So, continuing our example, growThetaTyVars {a} will return
{a,b,c,d,e}. Put another way, growThetaTyVars grows the set of
variables to include all variables that are mentioned in the same
constraint (transitively).

We use closeWrtFunDeps in places where we need to know which variables are
*always* determined by some seed set. This includes
  * when determining the mono-tyvars in decidePromotedTyVars. If `a`
    is going to be monomorphic, we need b and c to be also: they
    are determined by the choice for `a`.
  * when checking instance coverage, in
    GHC.Tc.Instance.FunDeps.checkInstCoverage

On the other hand, we use growThetaTyVars where we need to know
which variables *might* be determined by some seed set. This includes
  * deciding quantification (GHC.Tc.Gen.Bind.chooseInferredQuantifiers
    and decideQuantifiedTyVars
How can `a` determine (say) `d` in the example above without a fundep?
Suppose we have
  instance (b ~ a, c ~ a) => D (Maybe [a]) (Either b c)
Now, if `a` turns out to be a list, it really does determine b and c.
The danger in overdoing quantification is the creation of an ambiguous
type signature, but this is conveniently caught in the validity checker.

References 0

This Note does not link to any other.

Referenced by 6